VYPR
Medium severity4.8NVD Advisory· Published May 20, 2026· Updated May 20, 2026

CVE-2026-43617

CVE-2026-43617

Description

Rsync version 3.4.2 and prior contain an authorization bypass vulnerability in the rsync daemon's hostname-based access control list enforcement when configured with chroot. Attackers can bypass hostname-based deny rules by controlling the PTR record for their source IP address, allowing connections from hostnames that administrators intended to deny when reverse DNS resolution fails and defaults to UNKNOWN.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Rsync daemon 3.4.2 and prior with chroot can bypass hostname-based ACL denial if the attacker controls the PTR record and reverse DNS fails, causing the hostname to default to 'UNKNOWN'.

Vulnerability

In rsync daemon versions 3.4.2 and prior, when the daemon is configured with a chroot, the reverse DNS lookup of a connecting client is performed after entering the chroot. If the chroot environment lacks the necessary glibc files for DNS resolution (/etc/resolv.conf, /etc/nsswitch.conf, /etc/hosts, and NSS service modules), the lookup fails and the connecting hostname is set to "UNKNOWN". This allows an attacker to bypass hostname-based deny rules (e.g., "hosts deny = *.evil.example") because the "UNKNOWN" string does not match the deny pattern. IP-based ACLs are unaffected [1][2].

Exploitation

An attacker needs network access to the rsync daemon and control over the PTR record for their source IP address. The daemon must be configured with a chroot that does not contain the DNS resolution files. When the attacker connects, the rsync daemon performs a reverse DNS lookup inside the chroot, which fails due to missing files, and the connecting hostname is set to "UNKNOWN". The attacker can then connect from a hostname that the administrator intended to deny, bypassing the hostname-based ACL [1][2].

Impact

Successful exploitation results in an authorization bypass, allowing the attacker to connect to the rsync daemon even though their hostname was explicitly denied in the hosts deny directive. The impact is limited to situations where hostname-based ACLs are used; IP-based ACLs are not affected. This could lead to unauthorized read or write access to rsync shares, depending on other configuration settings [1][2].

Mitigation

The vulnerability is fixed in rsync version 3.4.3 [2][3]. Users should upgrade to this version. As a workaround, use IP-based ACLs ("hosts allow = ..." with CIDR notation) instead of hostname-based ACLs, or populate the chroot with the necessary DNS resolution files (/etc/resolv.conf, /etc/nsswitch.conf, /etc/hosts, and NSS shared objects) so that reverse lookup can succeed within the chroot [2].

AI Insight generated on May 21, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

2
  • Rsync/Rsyncreferences2 versions
    (expand)+ 1 more
    • (no CPE)
    • (no CPE)range: <=3.4.2

Patches

3
c38f20c5ffab

clientserver: fix hostname ACL bypass when using daemon chroot

https://github.com/rsyncproject/rsyncAndrew TridgellDec 31, 2025Fixed in 3.4.3via llm-release-walk
3 files changed · +134 1
  • clientserver.c+22 0 modified
    @@ -1312,6 +1312,28 @@ int start_daemon(int f_in, int f_out)
     	if (lp_proxy_protocol() && !read_proxy_protocol_header(f_in))
     		return -1;
     
    +	/* Do reverse DNS lookup before chroot/setuid. The result is cached,
    +	 * so the later client_name() call will use this cached value. This
    +	 * ensures hostname-based ACLs work even when DNS is unavailable
    +	 * after chroot.
    +	 *
    +	 * "reverse lookup" can be set globally OR per-module, so we also
    +	 * scan each module: a deployment with "reverse lookup = no" in the
    +	 * global section but "reverse lookup = yes" in a specific module
    +	 * still triggers a post-chroot lookup at access-check time
    +	 * (rsync_module() in this file), which would also fail in the
    +	 * chroot and turn hostname-based deny rules into silent bypasses. */
    +	{
    +		int need_reverse = lp_reverse_lookup(-1);
    +		int j, num_modules = lp_num_modules();
    +		for (j = 0; !need_reverse && j < num_modules; j++) {
    +			if (lp_reverse_lookup(j))
    +				need_reverse = 1;
    +		}
    +		if (need_reverse)
    +			(void)client_name(client_addr(f_in));
    +	}
    +
     	p = lp_daemon_chroot();
     	if (*p) {
     		log_init(0); /* Make use we've initialized syslog before chrooting. */
    
  • .github/workflows/macos-build.yml+1 1 modified
    @@ -41,7 +41,7 @@ jobs:
         - name: info
           run: rsync --version
         - name: check
    -      run: sudo RSYNC_EXPECT_SKIPPED=acls-default,chmod-temp-dir,chown-fake,devices-fake,dir-sgid,open-noatime,protected-regular,simd-checksum,xattrs-hlink,xattrs make check
    +      run: sudo RSYNC_EXPECT_SKIPPED=acls-default,chmod-temp-dir,chown-fake,daemon-chroot-acl,devices-fake,dir-sgid,open-noatime,protected-regular,simd-checksum,xattrs-hlink,xattrs make check
         - name: ssl file list
           run: rsync-ssl --no-motd download.samba.org::rsyncftp/ || true
         - name: save artifact
    
  • testsuite/daemon-chroot-acl.test+111 0 added
    @@ -0,0 +1,111 @@
    +#!/bin/sh
    +
    +# Copyright (C) 2026 by Andrew Tridgell
    +
    +# This program is distributable under the terms of the GNU GPL (see
    +# COPYING).
    +
    +# Regression test for GHSA-rjfm-3w2m-jf4f: a hostname-based "hosts deny"
    +# rule must still match when the daemon performs a 'daemon chroot' and
    +# the chroot does not contain the NSS files glibc needs for reverse DNS.
    +#
    +# Pre-fix, reverse DNS happened *after* the daemon chroot. With an empty
    +# chroot the NSS lookup failed, client_name() returned "UNKNOWN", and a
    +# deny rule referring to the connecting hostname silently failed to
    +# match.
    +#
    +# Two scenarios are exercised so we can distinguish the case the fix
    +# definitely covers from the per-module path that may still be
    +# vulnerable:
    +#   A. global  "reverse lookup = yes"           (covered by b6abdb4c)
    +#   B. only module "reverse lookup = yes"       (gap to verify)
    +
    +. "$suitedir/rsync.fns"
    +
    +case `uname -s` in
    +Linux*) ;;
    +*) test_skipped "test is Linux-specific (uses chroot+unshare)" ;;
    +esac
    +
    +# We need CAP_SYS_CHROOT. Re-exec under a user namespace if not root.
    +if ! chroot / /bin/true 2>/dev/null; then
    +    if [ -z "$RSYNC_UNSHARED" ] && unshare --user --map-root-user true 2>/dev/null; then
    +	echo "Re-running under unshare --user --map-root-user..."
    +	RSYNC_UNSHARED=1 exec unshare --user --map-root-user "$SHELL_PATH" $RUNSHFLAGS "$0"
    +    fi
    +    test_skipped "need CAP_SYS_CHROOT (root or unshare --user --map-root-user)"
    +fi
    +
    +# We need 127.0.0.1 to reverse-resolve to a real hostname while NSS is
    +# still working (i.e. before the daemon's chroot). The daemon will
    +# look that name up itself as part of its hostname-based ACL check;
    +# we then deny that name and assert the connection is rejected.
    +client_hostname=`getent hosts 127.0.0.1 2>/dev/null | awk 'NR==1 {print $2}'`
    +if [ -z "$client_hostname" ] || [ "$client_hostname" = "127.0.0.1" ]; then
    +    test_skipped "no reverse DNS for 127.0.0.1"
    +fi
    +
    +chrootdir="$scratchdir/chroot"
    +rm -rf "$chrootdir"
    +mkdir -p "$chrootdir/modroot"
    +echo "from chroot" > "$chrootdir/modroot/file1"
    +
    +conf="$scratchdir/test-rsyncd.conf"
    +logfile="$scratchdir/rsyncd.log"
    +
    +write_conf() {
    +    cat >"$conf" <<EOF
    +use chroot = no
    +log file = $logfile
    +daemon chroot = $chrootdir
    +reverse lookup = $1
    +hosts deny = $client_hostname
    +max verbosity = 4
    +
    +[chrootmod]
    +    path = /modroot
    +    read only = yes
    +    reverse lookup = $2
    +EOF
    +}
    +
    +# Run a transfer and return 0 if the daemon refused with @ERROR access
    +# denied (the expected outcome when the deny rule matches).
    +run_check() {
    +    label="$1"
    +
    +    rm -f "$logfile"
    +    rm -rf "$todir"
    +    mkdir -p "$todir"
    +
    +    out="$scratchdir/run.out"
    +
    +    RSYNC_CONNECT_PROG="$RSYNC --config=$conf --daemon" \
    +	$RSYNC -av localhost::chrootmod/ "$todir/" >"$out" 2>&1
    +    rc=$?
    +
    +    echo "----- $label (rsync exit $rc):"
    +    cat "$out"
    +    echo "----- daemon log:"
    +    [ -f "$logfile" ] && cat "$logfile"
    +    echo "-----"
    +
    +    grep -q '@ERROR.*access denied' "$out"
    +}
    +
    +# Scenario A: global reverse lookup. Covered by b6abdb4c.
    +write_conf yes yes
    +if ! run_check "Scenario A (global reverse lookup = yes)"; then
    +    test_fail "Scenario A: hostname deny rule was bypassed"
    +fi
    +
    +# Scenario B: only the per-module reverse-lookup setting is enabled.
    +# The b6abdb4c fix only pre-warms client_name()'s cache when the
    +# global setting is on, so the post-chroot lookup in this path may
    +# still produce "UNKNOWN" and bypass the deny rule.
    +write_conf no yes
    +if ! run_check "Scenario B (per-module reverse lookup only)"; then
    +    test_fail "Scenario B: hostname deny rule was bypassed (per-module reverse lookup with daemon chroot still has the bypass)"
    +fi
    +
    +exit 0
    
a0b9a8e989f6

NEWS: prepare 3.4.3 release entry with six CVEs

https://github.com/rsyncproject/rsyncAndrew TridgellMay 7, 2026Fixed in 3.4.3via llm-release-walk
1 file changed · +140 6
  • NEWS.md+140 6 modified
    @@ -1,7 +1,122 @@
    -# NEWS for rsync 3.4.3 (UNRELEASED)
    +# NEWS for rsync 3.4.3 (20 May 2026)
     
     ## Changes in this version:
     
    +### SECURITY FIXES:
    +
    +Six CVEs are fixed in this release.  All six are assigned by
    +VulnCheck as CNA.  Affected versions are 3.4.2 and earlier in every
    +case.  Three of the six (CVE-2026-29518, CVE-2026-43617,
    +CVE-2026-43619) require non-default daemon configuration to reach:
    +the first and third need `use chroot = no` for a module, the second
    +needs `daemon chroot = ...` set in rsyncd.conf.  Two (CVE-2026-43618,
    +CVE-2026-43620) are reachable from a normal pull or a normal
    +authenticated daemon connection.  The sixth (CVE-2026-45232) is
    +reachable only when `RSYNC_PROXY` is set and the proxy (or a MITM)
    +returns a pathological response.  Many thanks to the external
    +researchers who reported these issues.
    +
    +- CVE-2026-29518 (CVSS v4.0 7.3, HIGH): TOCTOU symlink race condition
    +  allowing local privilege escalation in daemon mode without chroot.
    +  An rsync daemon configured with "use chroot = no" was exposed to a
    +  time-of-check / time-of-use race on parent path components: a local
    +  attacker with write access to a module could replace a parent
    +  directory component with a symlink between the receiver's check and
    +  its open(), redirecting reads (basis-file disclosure) and writes
    +  (file overwrite) outside the module.  Default "use chroot = yes" is
    +  not exposed.  `secure_relative_open()` (added in 3.4.0 for
    +  CVE-2024-12086) was previously unused in the daemon-no-chroot
    +  case; the fix enables it there and reroutes the sender's
    +  read-path opens through it.  Reported by Nullx3D (Batuhan Sancak),
    +  Damien Neil and Michael Stapelberg.
    +
    +- CVE-2026-43617 (CVSS v3.1 4.8, MEDIUM): Hostname/ACL bypass on an
    +  rsync daemon configured with `daemon chroot = /X` in rsyncd.conf
    +  when the chroot tree lacks DNS resolution support.  The
    +  reverse-DNS lookup of the connecting client was performed *after*
    +  the daemon chroot had been entered; if /X did not contain the
    +  libc resolver fixtures (`/etc/resolv.conf`, `/etc/nsswitch.conf`,
    +  `/etc/hosts`, NSS service modules) the lookup failed and the
    +  connecting hostname was set to "UNKNOWN", causing hostname-based
    +  deny rules to silently fail open.  IP-based ACLs are unaffected.
    +  The per-module `use chroot` setting is unrelated to this issue.
    +  The fix performs the lookup before entering the daemon chroot.
    +  Reported by MegaManSec.
    +
    +- CVE-2026-43618 (CVSS v3.1 8.1, HIGH): Integer overflow in the
    +  compressed-token decoder enabling remote memory disclosure to an
    +  authenticated daemon peer.  The receiver accumulated a 32-bit
    +  signed counter without overflow checking; a malicious sender could
    +  trigger an overflow that, with careful manipulation, leaked process
    +  memory contents to the attacker -- environment variables,
    +  passwords, heap and library pointers -- significantly weakening
    +  ASLR.  The fix bounds the counter and adds wire-input validation in
    +  several adjacent places (defence-in-depth).  Workaround for older
    +  releases: `refuse options = compress` in rsyncd.conf.  Reported by
    +  Omar Elsayed.
    +
    +- CVE-2026-43619 (CVSS v3.1 6.3, MEDIUM): Symlink races on path-based
    +  system calls in "use chroot = no" daemon mode (generalisation of
    +  CVE-2026-29518).  Earlier fixes for symlink races on the receiver's
    +  open() call missed the same race class on every other path-based
    +  system call: chmod, lchown, utimes, rename, unlink, mkdir, symlink,
    +  mknod, link, rmdir and lstat.  The fix routes each affected
    +  path-based syscall through a parent dirfd opened under
    +  RESOLVE_BENEATH-equivalent kernel-enforced confinement (openat2 on
    +  Linux 5.6+, O_RESOLVE_BENEATH on FreeBSD 13+ and macOS 15+,
    +  per-component O_NOFOLLOW walk elsewhere).  Default "use chroot =
    +  yes" is not exposed.  Reported by Andrew Tridgell as a follow-on
    +  audit of CVE-2026-29518.
    +
    +- CVE-2026-43620 (CVSS v3.1 6.5, MEDIUM): Out-of-bounds read in the
    +  receiver's recv_files() enabling remote denial-of-service of any
    +  client pulling from a malicious server (incomplete fix of commit
    +  797e17f).  The earlier parent_ndx<0 guard added to send_files() was
    +  not applied to the visually-identical block in recv_files().  A
    +  malicious rsync server can drive any connecting client into a
    +  deterministic SIGSEGV by setting CF_INC_RECURSE in the
    +  compatibility flags and sending a crafted file list and transfer
    +  record.  inc_recurse is the protocol-30+ default, so no special
    +  options are required on the victim.  Workaround for older
    +  releases: `--no-inc-recursive` on the client.  Reported by Pratham
    +  Gupta.
    +
    +- CVE-2026-45232 (CVSS v3.1 3.1, LOW): Off-by-one out-of-bounds stack
    +  write in the rsync client's HTTP CONNECT proxy handler
    +  (`establish_proxy_connection()` in `socket.c`).  After issuing the
    +  CONNECT request, rsync read the proxy's first response line one
    +  byte at a time into a 1024-byte stack buffer with the bound
    +  `cp < &buffer[sizeof buffer - 1]`.  If the proxy (or a MITM in
    +  front of it) returned 1023+ bytes on that first line without a
    +  newline terminator, `cp` exited the loop pointing at a buffer slot
    +  the loop never wrote, leaving `*cp` holding stale stack data from
    +  the earlier `snprintf()` of the outgoing CONNECT request.  The
    +  post-loop logic then wrote a single `\0` one byte past the end of
    +  the buffer on the stack.  Reach is client-side only, and only when
    +  `RSYNC_PROXY` is set so rsync tunnels an `rsync://` connection
    +  through an HTTP CONNECT proxy.  The written byte is always `\0`
    +  and the offset is fixed by the buffer size, not attacker-chosen,
    +  so this is not an arbitrary-write primitive: practical impact is
    +  corruption of one adjacent stack byte and possible later
    +  misbehaviour or crash.  The fix detects the "buffer filled without
    +  finding `\n`" case explicitly by position and refuses the response
    +  with "proxy response line too long".  Reported by Aisle Research
    +  via Michal Ruprich (rsync-3.4.1-2.el10 QE).
    +
    +In addition to the six CVE fixes, this release adds defence-in-depth
    +hardening on several adjacent paths: bounded wire-supplied counts and
    +lengths in flist/io/acls/xattrs, a guard against length underflow in
    +cumulative `snprintf()` callers, a parent block-index bounds check on
    +the receiver, a NULL check in `read_delay_line()`, a lower ceiling on
    +`MAX_WIRE_DEL_STAT` to avoid signed-int overflow in the
    +`read_del_stats()` accumulator, rejection of hyphen-prefixed
    +remote-shell hostnames (defence-in-depth against argv-injection in
    +tooling that forwards untrusted input into the hostspec position;
    +reported by Aisle Research via Michal Ruprich), and a NULL-check on
    +`localtime_r()` in `timestring()` to keep a malicious server from
    +crashing the client by advertising a file with an out-of-range
    +modtime.
    +
     ### BUG FIXES:
     
     - Fixed a regression introduced by the 3.4.0 secure_relative_open()
    @@ -37,14 +152,33 @@
       with protocol < 29, top-level files). The test skips on
       platforms without a RESOLVE_BENEATH equivalent.
     
    -- runtests.py now errors early with a clear message when the test
    -  helper programs (`tls`, `trimslash`, `t_unsafe`, `wildtest`,
    -  `getgroups`, `getfsdev`) are missing, instead of letting many
    -  tests fail with confusing "not found" errors.
    +- Added regression tests for the new security fixes:
    +  `chmod-symlink-race.test`, `chdir-symlink-race.test`,
    +  `bare-do-open-symlink-race.test`, `alt-dest-symlink-race.test`,
    +  `copy-dest-source-symlink.test`, `sender-flist-symlink-leak.test`,
    +  `secure-relpath-validation.test`, `daemon-chroot-acl.test` and
    +  `daemon-refuse-compress.test`. The symlink-race tests skip on
    +  Cygwin, Solaris, OpenBSD and NetBSD (no RESOLVE_BENEATH
    +  equivalent on those platforms).
    +
    +- runtests.py now errors early with a clear message when any of
    +  the test helper programs (`tls`, `trimslash`, `t_unsafe`,
    +  `t_chmod_secure`, `t_secure_relpath`, `wildtest`, `getgroups`,
    +  `getfsdev`) are missing, instead of letting many tests fail with
    +  confusing "not found" errors.
     
     - Added OpenBSD and NetBSD CI jobs that run `make check` on those
       platforms.
     
    +- Added Ubuntu 22.04 and AlmaLinux 8 CI workflows so future
    +  backports to the two mainstream LTS families build and test on
    +  the same CI surface as trunk.
    +
    +- testsuite/protected-regular.test now runs unprivileged via
    +  `unshare` with user-namespace UID mapping, falling back to skip
    +  if `unshare`/`uidmap` is not available; previously it required
    +  real root.
    +
     - Added `symlink-dirlink-basis` to the Cygwin CI's expected-skipped
       list.
     
    @@ -5035,7 +5169,7 @@ to develop and test fixes.
     
     | RELEASE DATE | VER.   | DATE OF COMMIT\* | PROTOCOL    |
     |--------------|--------|------------------|-------------|
    -| ?? ??? 2026  | 3.4.3  |                  | 32          |
    +| 20 May 2026  | 3.4.3  |                  | 32          |
     | 28 Apr 2026  | 3.4.2  |                  | 32          |
     | 16 Jan 2025  | 3.4.1  |                  | 32          |
     | 15 Jan 2025  | 3.4.0  | 15 Jan 2025      | 32          |
    
24a3795e7f5b
https://github.com/rsyncproject/rsyncFixed in 3.4.3via llm-release-walk

Vulnerability mechanics

Root cause

"Reverse DNS lookup performed after entering the chroot jail causes hostname resolution to fail, returning "UNKNOWN" and bypassing hostname-based ACL deny rules."

Attack vector

An attacker who controls the PTR (reverse DNS) record for their source IP address can exploit this vulnerability against an rsync daemon configured with both `daemon chroot` and hostname-based ACL rules (e.g., `hosts deny = *.evil.example`). Because the reverse lookup is performed inside an empty chroot where DNS resolution fails, the daemon sees the connecting hostname as `"UNKNOWN"` and the deny rule never matches, allowing the attacker to connect from a hostname the administrator intended to block. The attack requires network access to the rsync daemon and the ability to set a PTR record for the attacker's IP [CWE-289]. IP-based ACLs are not affected.

Affected code

The vulnerability is in `clientserver.c` in the `start_daemon()` function. The reverse DNS lookup via `client_name()` was performed *after* the daemon had already entered the chroot jail. When the chroot directory lacked the NSS files required by glibc (e.g., `/etc/resolv.conf`, `/etc/nsswitch.conf`, `/etc/hosts`), the lookup failed and `client_name()` returned the string `"UNKNOWN"` instead of the connecting client's hostname.

What the fix does

The patch [patch_id=801812] adds a pre-chroot reverse DNS lookup in `start_daemon()` that calls `client_name(client_addr(f_in))` before the daemon enters the chroot. The result is cached by `client_name()`, so the later post-chroot call returns the cached hostname rather than attempting a fresh lookup that would fail. The fix also scans all configured modules for `reverse lookup = yes` to handle deployments where the global setting is `no` but a per-module setting enables reverse lookups, ensuring the cache is populated in all cases where a post-chroot lookup might otherwise occur.

Preconditions

  • configrsync daemon configured with 'daemon chroot' pointing to a directory that does not contain glibc NSS files (/etc/resolv.conf, /etc/nsswitch.conf, /etc/hosts)
  • configrsync daemon configured with hostname-based ACL rules (e.g., 'hosts deny = ')
  • networkAttacker controls the PTR record for their source IP address
  • networkAttacker has network access to the rsync daemon port

Generated on May 20, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

3

News mentions

0

No linked articles in our index yet.