From 3e231010dc4468b5702822465db31625fd973d96 Mon Sep 17 00:00:00 2001 From: damianrickard <154095072+damianrickard@users.noreply.github.com> Date: Sun, 21 Jun 2026 20:05:29 -0400 Subject: [PATCH] macOS: search system directories before /usr/local/bin for binaries (#1790) On macOS, Process::FindSystemBinary() searched /usr/local/bin first, so a user-writable /usr/local/bin (the default on Homebrew installs) could shadow system tools. This resolver is also used to locate privileged binaries during privilege elevation: CoreService.cpp resolves "sudo" (and "true") through it both when probing for an active sudo session and when launching the elevated helper, and the admin password is written to that sudo process's stdin. On a typical Homebrew install /usr/local is owned by the (non-root) user, so a planted /usr/local/bin/sudo would be selected ahead of /usr/bin/sudo and could capture the admin password, leading to privilege escalation. Reorder the macOS list to {/usr/bin, /bin, /usr/sbin, /sbin, /usr/local/bin} so system locations always win. The binaries actually resolved through this function on macOS (sudo, true, fsck, the terminal helper used for filesystem checks and its dependencies, and non-APFS formatters) live in system directories, so /usr/local/bin is kept only as a last-resort fallback and can no longer shadow them. (diskutil, hdiutil and newfs_apfs are invoked via absolute paths and were never affected.) Co-authored-by: Damian Rickard --- src/Platform/Unix/Process.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Platform/Unix/Process.cpp b/src/Platform/Unix/Process.cpp index 92a4f30b..b50add5c 100644 --- a/src/Platform/Unix/Process.cpp +++ b/src/Platform/Unix/Process.cpp @@ -44,9 +44,15 @@ namespace VeraCrypt return ""; } - // Default system directories to search for executables + // Default system directories to search for executables. + // On macOS, system locations are searched before /usr/local/bin so that + // a user-writable /usr/local/bin (the default on Homebrew installs) + // cannot shadow system tools. This matters because this resolver is + // also used for privileged binaries such as sudo during elevation + // (see CoreService.cpp); a planted /usr/local/bin/sudo would otherwise + // receive the admin password. #ifdef TC_MACOSX - const char* defaultDirs[] = {"/usr/local/bin", "/usr/bin", "/bin", "/usr/sbin", "/sbin"}; + const char* defaultDirs[] = {"/usr/bin", "/bin", "/usr/sbin", "/sbin", "/usr/local/bin"}; #elif TC_FREEBSD const char* defaultDirs[] = {"/sbin", "/bin", "/usr/sbin", "/usr/bin", "/usr/local/sbin", "/usr/local/bin"}; #elif TC_OPENBSD