Introduction
A classic race condition in rsync's daemon mode has been quietly sitting in the codebase for years, waiting for the right configuration to become exploitable. CVE-2026-29518 is a time of check to time of use (TOCTOU) flaw in rsync versions before 3.4.3 that allows a local attacker with write access to a module directory to escape the intended file boundary via symlink substitution, enabling arbitrary file writes and reads on the host system.
What makes this particularly interesting is that the mitigation function (secure_relative_open()) already existed in the codebase since rsync 3.4.0, having been introduced for a different vulnerability (CVE-2024-12086). It simply was never wired into the specific code path that handles daemon operation without chroot confinement. The fix, shipped in rsync 3.4.3 on May 20, 2026, activates this function where it was needed all along.
Technical Information
Root Cause: The TOCTOU Window
The vulnerability is classified under CWE-367 (Time of check Time of use Race Condition) and resides in rsync's daemon mode when configured with use chroot = no. While this is not the default setting, it is a common configuration in environments where the daemon process lacks the privileges to call chroot() or where administrators need access to paths outside a single directory tree.
In the vulnerable code path, the receiver performs two distinct operations sequentially:
- Check: The receiver validates the incoming file path, confirming it resolves to a location within the intended module directory.
- Use: The receiver calls
open()on that validated path to perform the actual file operation.
Between these two operations, there is a window during which the filesystem state can change. A local attacker with write access to the module directory can exploit this window by replacing a parent directory component with a symbolic link pointing outside the module boundary. When the open() call executes, it follows the newly planted symlink, and the file operation lands on an attacker controlled location outside the intended directory.
Attack Flow
The exploitation sequence proceeds as follows:
- The attacker establishes an authenticated connection to the rsync daemon. The connection must have compression enabled, which is the default behavior for protocol version 30 and above when both peers advertise compression support.
- The attacker identifies a module configured with
use chroot = nowhere they have write access. - The attacker initiates a file transfer that will cause the receiver to validate and then open a file path containing multiple directory components.
- During the precise window between the receiver's path validation and its
open()system call, the attacker replaces one of the parent directory components with a symlink pointing to a sensitive location (for example,/etc/or another privileged directory). - The
open()call follows the symlink, and the file write or read operation occurs outside the module boundary.
This race can be exploited in two directions:
- Writes: Redirected file writes allow the attacker to create or overwrite arbitrary files on the system. When the daemon runs as root, this directly enables privilege escalation by modifying sensitive system files such as
/etc/passwd,/etc/shadow, or cron configurations. - Reads: Redirected basis file reads allow the attacker to disclose the contents of privileged files through the daemon's response data.
Why Chroot Matters
The default rsync daemon configuration uses use chroot = yes, which calls chroot() to confine the daemon process to the module directory at the kernel level. In this configuration, even if an attacker wins the race and plants a symlink, the kernel prevents any path resolution from escaping the chroot jail. The vulnerability is therefore strictly conditional on the non default use chroot = no setting.
Patch Information
The fix was delivered in rsync 3.4.3, released on May 20, 2026, via PR #895 in the RsyncProject/rsync repository. This was a combined pull request by maintainer Andrew Tridgell (tridge) that bundled fixes for six CVEs across 21 commits, 40 changed files, with 3,100 additions and 178 deletions. It was merged the same day it was opened.
Core Fix: Commit ed649cda (Receiver Side)
This commit is the primary fix. It activates the secure_relative_open() function in syscall.c for the daemon no chroot code path. This function already existed since rsync 3.4.0 (added for CVE-2024-12086) but was not being used in the exact scenario this vulnerability exploits. The commit enables it by setting use_secure_symlinks in clientserver.c's rsync_module() function and reroutes the receiver's basis file open in receiver.c through it.
The function eliminates the race window by walking each parent path component anchored at a trusted directory file descriptor (dirfd), using kernel enforced symlink following restrictions at each step:
- Linux 5.6+: Uses
openat2()with theRESOLVE_BENEATHflag, instructing the kernel to reject any path component that would escape the starting directory via symlinks or..traversal. - FreeBSD 13+ and macOS 15+: Uses
O_RESOLVE_BENEATH, the BSD equivalent. - Other platforms: Falls back to a per component walk using
O_NOFOLLOWon each directory in the path, manually refusing to follow symlinks.
Because the kernel itself enforces confinement at every step, the race window is eliminated entirely. Even if an attacker swaps a directory for a symlink between the check and the open, the kernel rejects the traversal.
Sender Side Fix: Commit dbfeb532
This commit addresses the same TOCTOU race on the sender side. The sender's change_pathname() used chdir() to descend into subdirectories, which followed symlinks freely. An attacker could race to swap a directory for a symlink between the chdir() and the subsequent file open(), allowing reads of privileged files through the daemon. The fix reconstructs the full relative path (F_PATHNAME + fname) and opens the file via secure_relative_open() from the trusted module_dir root. Because this approach is CWD independent, the chdir race is entirely neutralized.
Additional Hardening
Beyond the two primary commits, several follow on commits within the same PR hardened adjacent code paths against the same race class (tracked under the related CVE-2026-43619): securing change_dir() itself against chdir escape (9401f882), adding do_chmod_at() and a full suite of do_*_at() wrappers for chmod, lchown, utimes, rename, unlink, mkdir, symlink, mknod, link, rmdir, and lstat (ef7b6205, 65bd4ce9), and hardening copy_file() source and destination opens (42ecda33).
Regression Tests
The release ships with a comprehensive regression test suite: chmod-symlink-race.test, chdir-symlink-race.test, bare-do-open-symlink-race.test, alt-dest-symlink-race.test, copy-dest-source-symlink.test, and sender-flist-symlink-leak.test. These tests skip on platforms lacking RESOLVE_BENEATH equivalents (Cygwin, Solaris, OpenBSD, NetBSD).
All affected versions are rsync 3.4.2 and earlier. Users should upgrade to 3.4.3 via the tagged release on GitHub or tarballs at rsync.samba.org/ftp/rsync/src/.
Affected Systems and Versions
- Affected: All rsync versions before 3.4.3
- Fixed in: rsync 3.4.3
- Vulnerable configuration: The rsync daemon must be running with
use chroot = noinrsyncd.conf. The default setting ofuse chroot = yesis not vulnerable. - Additional prerequisite: The attacker must have write access to a module path and an authenticated daemon connection with compression enabled (default for protocol 30+).
It is worth noting that while CVE-2026-29518 specifically requires the non default chroot configuration, the 3.4.3 release also patches vulnerabilities reachable under standard operating conditions. The full set of CVEs addressed in this release includes:
| CVE Identifier | CVSS Score | Description | Configuration Requirement |
|---|---|---|---|
| CVE-2026-29518 | 7.3 (High) | TOCTOU symlink race, local privilege escalation | Requires use chroot = no |
| CVE-2026-43619 | 6.3 (Medium) | Symlink races on path based system calls | Requires use chroot = no |
| CVE-2026-43617 | Not Provided | Security flaw requiring non default daemon config | Requires daemon chroot =... |
| CVE-2026-43618 | Not Provided | Security flaw reachable from normal pull | Standard configuration |
| CVE-2026-43620 | Not Provided | Security flaw reachable from normal pull | Standard configuration |
| CVE-2026-45232 | Not Provided | Off by one out of bounds stack write | Requires RSYNC_PROXY |
Organizations should deploy the update universally rather than only targeting servers with disabled chroot settings.
Vendor Security History
The RsyncProject has a documented history of security challenges specifically related to disabled chroot environments. In April 2004, the rsync 2.6.1 release notes highlighted a security fix for a daemon problem when chroot is not enabled. The maintainers explicitly warned users running a non read only rsync daemon with chroot disabled to upgrade, especially if the user privileges were anything above nobody. Over two decades later, CVE-2026-29518 demonstrates that the same configuration surface continues to present security challenges.
The secure_relative_open() function that forms the core of the fix was originally introduced in rsync 3.4.0 for CVE-2024-12086 but was not activated in the daemon no chroot code path. This gap between having a security mechanism available and actually deploying it across all relevant code paths is a common pattern in large codebases and underscores the importance of thorough security audits that consider all configuration permutations.
The 3.4.3 release, addressing six CVEs simultaneously, represents a significant security hardening effort for the project, with particular attention to eliminating an entire class of symlink based race conditions rather than addressing them one at a time.
References
- CVE-2026-29518 Detail (NVD)
- PR #895: Combined security fixes for 3.4.3 release (GitHub)
- Commit ed649cda: Receiver side fix (GitHub)
- Commit dbfeb532: Sender side fix (GitHub)
- Commit 8471fdd1: Combined security fixes diff (GitHub)
- oss-sec: rsync 3.4.3 released: six CVEs
- VulnCheck Advisory: Rsync TOCTOU Race Condition
- rsync 3.4.3 Release (GitHub)
- NEWS for rsync (Samba.org)



