Repository navigation
Conversation
On Windows, an archive entry whose final component is a DOS device name (NUL, CON, COM1-9, LPT1-9, ..., with or without extension) makes File::create open the device itself: decompression streams archive-controlled bytes into the device and then aborts mid-archive. A ':' in an entry name silently writes an NTFS alternate data stream, hiding payload from normal file listings. Funnel the check through the shared validators: validate_entry_path (tar, 7z, rar; now also zip after enclosed_name) and validate_symlink_target. Zip/7z skip the entry with a warning following their unsafe-name convention; tar and rar refuse the archive. Compression skips walked files with such names and rejects them as explicit inputs so opening a device (e.g. reading CON hangs on console input) cannot happen. Both checks are Windows-only: NUL and ':' are legal file names elsewhere, and behavior there is unchanged.
Collaborator
|
Author
|
Addressed in 68312f9 + a8b0dc5. Added |
Collaborator
|
COM¹ COM² COM³ LPT¹ LPT² and LPT³ are also reserved as device names |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1090.
Bugs (Windows)
Two ways a crafted archive writes outside the intended destination:
NUL/CON/COM1-COM9/LPT1-LPT9(with or without extension —NUL.txtstill resolves to the device) makesFile::createopen the device itself. Decompression streams attacker-controlled bytes into the device, then aborts mid-archive (os error 1), leaving the archive half-extracted. On hosts with a real COM/LPT/console this writes to hardware; readingCONduring compression would hang on console input.:: an entryfile:ads.txtsilently writes a hidden alternate data streamfile:ads.txt:$DATA— invisible to normaldirlistings (verified viaGet-Item -Stream *).Fix (+181/-7)
New
windows_unsafe_name_reason()inutils/fs.rs— per-component check for:(on raw encoded bytes, so non-UTF-8 names can't smuggle one pastto_str()) and reserved device stems (stem before first., case-insensitive, trailing-space tolerant —NUL .txtis caught too;nul2/COM10/.nulunaffected).Wired through the existing shared validators:
validate_entry_path(tar, 7z, rar; zip too — applied toenclosed_name's output): zip/7z warn+skip the hostile entry (their unsafe-name convention — a hostile member no longer aborts the whole archive); tar/rar refuse with a clear error.validate_symlink_target: symlink →NUL/ADS targets refused.unpack_in(previously unvalidated on Windows).Design choices: reject/skip, not rename (consistent with ouch's
..posture);cfg!(windows)runtime gate inside an always-compiled helper — zero#[cfg]at call sites and unit-testable on Linux CI.NULandfile:ads.txtremain legal on Linux — verified unchanged.Verified on real Windows
CONentryos error 1abort, rest lostNUL/LPT1in zip/tar/tar.gzos error 1/ device writefile:ads.txtNULNUL,CONcargo test132/0 on Linux; Windows cross-build clean;fmt/clippyclean.listoutput intentionally unchanged (informational only).