| Version | Supported |
|---|---|
| 0.6.x | ✅ |
| 0.5.x | |
| < 0.5 | ❌ |
If you discover a security vulnerability in oc-rsync, please report it responsibly:
- Do not open a public GitHub issue for security vulnerabilities
- Email the maintainer directly at: [email protected]
- Include:
- Description of the vulnerability
- Steps to reproduce
- Potential impact assessment
- Any suggested fixes (optional)
You can expect:
- Initial acknowledgment within 48 hours
- Regular updates on the fix progress
- Credit in the security advisory (unless you prefer anonymity)
oc-rsync leverages Rust's memory safety to eliminate entire vulnerability classes:
- No buffer overflows: Rust's bounds checking prevents out-of-bounds memory access
- No use-after-free: Rust's ownership system prevents dangling pointer access
- No uninitialized memory: All memory must be initialized before use
- No data races: Rust's type system prevents concurrent memory access bugs
Crates that enforce #![deny(unsafe_code)] with no allow-listed exceptions:
daemon,cli,core,transfer,batch,filters,signature,match,bandwidth,logging,logging-sink,branding,rsync_io,compress,apple-fs,flist- business logic, parsers, orchestration, and high-level I/O wrappers
Crates with #![deny(unsafe_code)] and targeted #[allow(unsafe_code)] for documented FFI/SIMD boundaries:
metadata- Ownership and privilege FFI (UID/GID lookup viagetpwuid_r/getgrnam_r,setuid/setgid,setattrlist)protocol- One isolated#[allow]inmultiplex::helpersfor performance-critical frame parsingengine- Denies unsafe outside tests (#![cfg_attr(not(test), deny(unsafe_code))]) with targeted#[allow(unsafe_code)]on platform FFI (prefetch, buffer pool,CopyFileExW)platform- Daemonization, signal handlers, environment isolation, and chroot syscallschecksums- SIMD intrinsics for MD4/MD5 and rolling checksums (AVX2, AVX-512, SSE2, SSSE3, SSE4.1, NEON, WASM), with scalar fallbacks and parity testsfast_io- Platform I/O syscalls (sendfile, io_uring, mmap,copy_file_range, IOCP,WSARecv/WSASend,setsockopt), with standard I/O fallbackswindows-gnu-eh- Windows GNU exception handling shims (properly documented)
Long-term direction. Unsafe code is being consolidated into fast_io as the single crate permitted to wrap platform FFI directly; new unsafe code goes there and is exposed via safe public APIs. New #[allow(unsafe_code)] annotations in any other crate require explicit review.
Note: OS-level race conditions (TOCTOU) remain possible at filesystem boundaries; Rust's memory safety does not prevent them.
oc-rsync monitors upstream rsync CVEs to verify continued non-applicability. Recent CVEs and our status:
| CVE | Upstream Issue | oc-rsync Status | Reason |
|---|---|---|---|
| CVE-2024-12084 | Heap overflow in checksum parsing | Not vulnerable | Rust Vec handles dynamic sizing |
| CVE-2024-12085 | Uninitialized stack buffer leak | Not vulnerable | Rust requires initialization |
| CVE-2024-12086 | Server leaks client files | Not vulnerable | Strict path validation |
| CVE-2024-12087 | Path traversal via --inc-recursive | Not vulnerable | Path sanitization |
| CVE-2024-12088 | --safe-links bypass | Mitigated | Rust path handling |
| CVE-2024-12747 | Symlink race condition | Mitigated | TOCTOU is OS-level |
- Subscribe to rsync-announce: https://lists.samba.org/mailman/listinfo/rsync-announce
- Monitor NVD: https://nvd.nist.gov/vuln/search?query=rsync
- GitHub Security Advisories: Watch this repository for security advisories
For each new upstream rsync CVE:
- Analyze the root cause (memory corruption, logic error, etc.)
- Check if oc-rsync has equivalent code paths
- Verify Rust's safety guarantees apply
- Document the analysis in this file
- If vulnerable, issue a security advisory and patch
The protocol crate includes cargo-fuzz targets for security-critical parsing:
cd crates/protocol/fuzz
cargo +nightly fuzz run fuzz_varint
cargo +nightly fuzz run fuzz_delta
cargo +nightly fuzz run fuzz_multiplex_frame
cargo +nightly fuzz run fuzz_legacy_greetingSee crates/protocol/fuzz/README.md for detailed fuzzing instructions.
These cover operationally relevant trade-offs in the current code base and how to mitigate them.
recycle_buffer(buf_id) in the io_uring path validates that buf_id falls within the registered buffer pool using debug_assert!. In release builds the assertion compiles out, so a corrupted or attacker-influenced buf_id reaching this code path would index out of range and either produce undefined behaviour inside the io_uring crate or — more likely — be caught by the kernel as an invalid SQE. A defense-in-depth fix to upgrade the check to a release-mode bound is tracked; until it lands, do not expose the io_uring path to untrusted protocol input.
io_uring buffer-group IDs (bgid) live in a 16-bit namespace. The provided-buffer ring helpers in fast_io cap allocation at this bound, and exhaustion returns an error rather than wrapping. Long-running daemons that churn ring groups should monitor for the bounded error and recycle.
If the SSH transport itself compresses the stream (Compression yes in ssh_config or a cipher with built-in compression), running oc-rsync -z will compress payloads twice. The amplification surface is small in practice but adds CPU and can mask compressor-specific bugs. Disable one layer; the canonical choice is to leave compression to rsync (-z / --compress) and disable it in SSH.
oc-rsync --daemon does not terminate TLS natively. To expose the daemon over an untrusted network, deploy it behind one of:
- stunnel in front of
rsync://-style daemon traffic - SSH tunnel (
ssh -Lto a localhost-bound daemon) - A reverse proxy that performs TLS termination (e.g., HAProxy in TCP mode)
Bind the daemon itself to 127.0.0.1 (or a private VPC interface) and route external clients exclusively through the TLS terminator.
See docs/deployment/daemon-tls.md for runnable recipes covering stunnel, ssh -L, and HAProxy TCP-mode configurations, hardened systemd unit excerpts, and nftables/iptables rules that deny external access to the daemon's loopback port.
In addition to use chroot = yes, prefer:
numeric ids = yesso uid/gid mapping does not depend on the daemon'spasswd/grouprefuse options = delete *for read-only mirrorshosts allow/hosts denyACLs at the daemon layer (these run before authentication)secrets filepermissions of0600, owned by the daemon user only
When running oc-rsync --daemon:
- Use chroot: Configure
use chroot = yesin rsyncd.conf - Restrict modules: Only expose necessary paths
- Authentication: Use
auth usersandsecrets filefor access control - Network security: Run behind a firewall, use SSH tunneling for remote access
- Read-only modules: Use
read only = yeswhere possible
- Verify server identity: Use SSH for transport when possible
- Careful with --delete: Ensure you're syncing to the intended destination
- Review exclude patterns: Avoid accidentally transferring sensitive files
Security researchers who have contributed to oc-rsync's security:
- (Your name could be here - report responsibly!)