Skip to content

fix(transfer): reject Windows drive prefixes from untrusted senders + audit#3496

Merged
oferchen merged 1 commit into
masterfrom
docs/windows-path-edge-cases
May 1, 2026
Merged

fix(transfer): reject Windows drive prefixes from untrusted senders + audit#3496
oferchen merged 1 commit into
masterfrom
docs/windows-path-edge-cases

Conversation

@oferchen
Copy link
Copy Markdown
Owner

@oferchen oferchen commented May 1, 2026

Summary

  • Catalogs Windows-specific path-handling hazards beyond the wire-encoding work already covered by the existing windows-path-normalization.md and windows-path.md audits: drive-relative paths, UNC, \\?\ round-trips, Path::canonicalize semantics, reparse points / junctions, long paths, and reserved names. Each hazard is mapped to current oc-rsync code and test coverage in a new audit at docs/audits/windows-path-edge-cases.md.
  • Identifies and fixes one self-contained Windows-only bug (W1 in the audit): on Windows, Path::has_root() returns false for drive-relative paths such as C:foo, but dest_dir.join("C:foo") discards dest_dir entirely (Path::join semantics). An untrusted sender could therefore emit a wire path with a drive letter, UNC prefix, or \\?\ extended prefix to escape the destination tree. The receiver's sanitize_file_list now rejects any path whose first component is Component::Prefix(_) on Windows.
  • Adds two Windows-only unit tests in crates/transfer/src/receiver/tests.rs covering both the trusted and untrusted code paths.

The fix is #[cfg(windows)]-gated, lives in a single function, and does not touch wire protocol or shared logic. Behaviour on Linux and macOS is unchanged.

No matching tracking issue was found in gh issue list for "windows path", "path normalization", or "windows in:title path".

Test plan

  • CI Windows runner (windows-latest) passes, including the two new #[cfg(windows)] tests windows_drive_relative_path_rejected_when_untrusted and windows_drive_relative_path_allowed_when_trusted.
  • CI fmt+clippy and Linux/macOS/Linux-musl matrices pass.
  • No behaviour change on non-Windows platforms - the new check is gated on #[cfg(windows)].

… audit

On Windows, `Path::has_root()` returns false for drive-relative paths
such as `C:foo`, but `dest_dir.join("C:foo")` discards `dest_dir`
(Path::join semantics for prefixed inputs), letting a malicious sender
escape the destination tree. The receiver's sanitize_file_list now
rejects any path whose first component is `Component::Prefix(_)` on
Windows. Adds two unit tests for the trusted/untrusted paths.

Also catalogs Windows path-handling hazards beyond the wire-encoding
work (drive prefixes, UNC, `\\?\`, canonicalize round-trips, reparse
points, long paths, reserved names) in `docs/audits/windows-path-edge-cases.md`.
@github-actions github-actions Bot added the bug Something isn't working label May 1, 2026
@oferchen oferchen merged commit 47fea76 into master May 1, 2026
47 checks passed
oferchen added a commit that referenced this pull request May 1, 2026
…3497)

Confirms that every sender-side wire-emit site for filenames and
symlink targets routes through `path_bytes_to_wire`, normalizing
native `\` to `/` on Windows. Retires Finding F1 from
`windows-path-normalization.md`. Receiver-side counterpart already
landed in PR #3496.
@oferchen oferchen deleted the docs/windows-path-edge-cases branch May 1, 2026 21:09
oferchen added a commit that referenced this pull request May 5, 2026
… audit (#3496)

On Windows, `Path::has_root()` returns false for drive-relative paths
such as `C:foo`, but `dest_dir.join("C:foo")` discards `dest_dir`
(Path::join semantics for prefixed inputs), letting a malicious sender
escape the destination tree. The receiver's sanitize_file_list now
rejects any path whose first component is `Component::Prefix(_)` on
Windows. Adds two unit tests for the trusted/untrusted paths.

Also catalogs Windows path-handling hazards beyond the wire-encoding
work (drive prefixes, UNC, `\\?\`, canonicalize round-trips, reparse
points, long paths, reserved names) in `docs/audits/windows-path-edge-cases.md`.
oferchen added a commit that referenced this pull request May 5, 2026
…3497)

Confirms that every sender-side wire-emit site for filenames and
symlink targets routes through `path_bytes_to_wire`, normalizing
native `\` to `/` on Windows. Retires Finding F1 from
`windows-path-normalization.md`. Receiver-side counterpart already
landed in PR #3496.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant