The privileged CoreService handler for SetFileOwnerRequest passed the
client-supplied path straight to chown() as root with no validation --
unlike the adjacent APFS formatter handler, which strictly validates its
device argument. Every legitimate macOS caller of the elevated
SetFileOwner targets a real disk device node (/dev/[r]diskN[sM]), so a
crafted IPC request, or a symlink planted at the target, could otherwise
make the root process change ownership of an arbitrary path.
Validate the target service-side: require the strict device-path form
already used by the formatter, and lstat() it to confirm a block or
character device (rejecting symlinks rather than following them) before
the chown.
Co-authored-by: Damian Rickard <damian@rickard.us>
APFS volume creation can still fail with Permission denied after preparing the raw and block device aliases because newfs_apfs performs privileged APFS container and volume operations beyond opening the device nodes.
Route APFS formatting through the elevated CoreService path for non-root macOS runs. Keep the elevated interface narrow by sending only the target device and invoking user UID/GID, validate the device path on the privileged side, rebuild the formatter arguments there, and execute /sbin/newfs_apfs by absolute path to avoid PATH shadowing.
Pass -U/-G so the created filesystem preserves the invoking user ownership. Apply the same path to GUI and text-mode creation.
When normal filesystem unmount fails, the Linux path could stop before cleaning VeraCrypt mapper, loop and FUSE objects. Add an explicit emergency dismount request that is only reached after interactive confirmation.
The recovery path lazy-detaches mounted filesystems, uses deferred dmsetup removal for VeraCrypt mapper devices, detaches loop devices, and keeps normal force/ignoreOpenFiles behavior unchanged.
The read loop that captures stderr from the sudo child process used
`vector<char> buffer(4096); buffer.clear();` followed by
`read(fd, &buffer[0], buffer.capacity())`. This has two instances of
undefined behavior:
1. `operator[](0)` on a vector with `size() == 0` violates the C++
standard precondition `n < size()`. libstdc++ built with
`-D_GLIBCXX_ASSERTIONS` aborts the process with:
stl_vector.h:1128: Assertion '__n < this->size()' failed.
2. `buffer.begin() + bytesRead` on the same empty vector constructs
an iterator past `end()`, also UB.
`-D_GLIBCXX_ASSERTIONS` is in the default build flags of Arch Linux,
Fedora, and several other distributions. On those systems, the
unprivileged helper process aborts as soon as sudo writes anything
to stderr (a password prompt, a 'user is not in the sudoers file'
error, etc.). The main process then sees EOF on the service output
pipe, and throws `InsufficientData`, which renders to the user as
'Not enough data available'. A second mount attempt fails at
`File::Write` because the helper is dead and the pipe is broken,
producing the bare message 'VeraCrypt::File::Write:395'.
Fix by replacing `buffer` with a plain `char[4096]` and using
`reserve(4096)` on `errOutput` to preserve the original
pre-allocation intent. No behavioral change on systems where the UB
happened to work; aborts are eliminated on systems where the
assertions fire.
Reported-by: multiple users, see veracrypt/VeraCrypt#1550,
veracrypt/VeraCrypt#1446, veracrypt/VeraCrypt#844
Co-authored-by: rabbit <rabbit@github>
When VeraCrypt is run as an AppImage, the veracrypt binary resides in a SquashFS mount under /tmp which is inaccessible to root. Using this path with sudo results in a "command not found" error.
This patch detects the AppImage environment by checking both APPIMAGE and APPDIR variables, ensuring the executable path starts with APPDIR and that APPDIR starts with the expected "/tmp/.mount_Veracr" prefix. In this scenario, the AppImage file itself (APPIMAGE) is used as the executable for sudo, resolving the elevation issue.
Added security checks to prevent mounting VeraCrypt volumes on system directories (like /usr/bin) or directories in the user's PATH, which could theoretically allow execution of malicious binaries instead of legitimate system binaries.
Key changes:
- Block mounting on protected system directories (/usr, /bin, /lib, etc.)
This restriction cannot be overridden
- Block mounting on directories present in user's PATH environment variable
This can be overridden with --allow-insecure-mount flag
- Add visual warnings (red border, "[INSECURE MODE]") when mounting on PATH directories is allowed
- Handle symlinks properly when checking paths
- Add new error messages for blocked mount points
To override PATH-based restrictions only (system directories remain protected):
veracrypt --allow-insecure-mount [options] volume mountpoint
Security Impact: Low to Medium
The attack requires either:
- User explicitly choosing a system directory as mount point instead of using VeraCrypt's default mount points
- Or attacker having both filesystem access to modify favorites configuration AND knowledge of the volume password
Default mount points are not affected by this vulnerability.
Security: CVE-2025-23021
This commit fixes a critical security vulnerability where VeraCrypt could be tricked into executing malicious binaries with elevated privileges. The vulnerability has two severe implications:
1. When sudo's secure_path option is disabled, attackers could execute malicious binaries with root privileges by placing them in user-writable PATH directories (e.g., making "sudo mount" execute a malicious mount binary)
2. By placing a malicious sudo binary in PATH, attackers could intercept and steal the user's password when VeraCrypt prompts for sudo authentication
The vulnerability allowed attackers to place malicious binaries in user-writable directories that appear in PATH before system directories, potentially leading to privilege escalation and credential theft.
Key changes:
- Implement FindSystemBinary() to locate executables in secure system paths
- Replace all relative binary paths with absolute paths for system commands
- Add security checks for executable permissions
- Update process execution to use absolute paths for:
* sudo
* mount
* fsck
* terminal emulators
* file managers
* system utilities (hdiutil, mdconfig, vnconfig, lofiadm)
The fix ensures all system binaries are called using their absolute paths from secure system directories, preventing both privilege escalation through PATH manipulation and password theft through sudo hijacking.
Security: CVE-2024-54187
This update simplifies the logic for detecting active sudo sessions by checking the exit code of the sudo -n -l command, which reliably returns 0 if a session is active.
Additionally, this approach is now applicable to recent macOS versions, as they no longer have the sudo bug that previously prevented us from using this method.
The behaviour of `wc -l` is different on FreeBSD, in which the stdout
result is padded by spaces in the beginning, which causes that the
result[0] is not actually the value we care about. This patch adds
a translate removing all whitespace from the output.
Currently if you fail the privilege escalation prompt, the second
one and consecutively every second will be ignored. This is because
if we do not --use-dummy-sudo-password and are on Linux/FreeBSD,
we will be prompted for password twice for one evaluation in the
while(!ElevatedServiceAvailable) loop.
For the fix, we make sure that we run the prompt only once for each
case.