Skip to content

refuse a ':' in a path a mount point serves - #2643

Merged
yhirose merged 3 commits into
yhirose:masterfrom
metsw24-max:mount-path-stream-name
Oct 26, 2026
Merged

yhirose merged 3 commits into
yhirose:masterfrom
metsw24-max:mount-path-stream-name

Conversation

@metsw24-max

Copy link
Copy Markdown
Contributor

b4b2458 made is_valid_path refuse a segment ending in . or a space because Windows maps those names onto another file, but : still gets through, and on NTFS it does the same job by naming a stream of the file. A request for /dir/test.html::$DATA opens the default stream of dir/test.html, so a set_pre_routing_handler() guard on /dir/test.html is passed and the file is served anyway, while /setup.exe:Zone.Identifier serves the stream Windows attaches to downloaded files, which records the URL they came from. _fullpath keeps the stream suffix, so the containment check against the resolved base still passes, and as far as I can tell the UCRT _wstat and CreateFile2 both open the stream (MinGW's _wstat may refuse it). I noticed it while reading the alias cases the README still lists, where stream names are not mentioned. Refusing : in is_valid_path closes it, and I have applied it on every platform to match the dot and space rule, so the mapping from req.path to a file stays the same wherever the server runs. The cost should be small, though a POSIX deployment serving file names with a colon would now get a 404 for them.

Reviewer note. I could only run the macOS no-TLS and split builds: IsValidPathTest.RejectsStreamNames fails before the change and passes after, while the two new MountTest.AliasedPathDoesNotPassPreRoutingGuard cases only reach the stream path on the Windows (MSVC) job, so I have not observed that half directly. If you would rather keep : on POSIX, scoping the check to _WIN32 is a one-line change.

metsw24-max and others added 3 commits October 25, 2026 13:20
On NTFS a ':' in a file name selects a stream of the file, so
"/a.txt::$DATA" serves a.txt past a pre-routing check on "/a.txt",
and "/a.txt:name" serves a named stream such as Zone.Identifier.
is_valid_path now refuses ':' on every platform, as it does a segment
ending in '.' or a space.
An NTFS stream name is the only thing ':' means in a path, and only on
Windows. Elsewhere it is an ordinary file name character, so a file such
as 2024-01-01T10:00:00.log would stop being served. The test pins both
sides.
@yhirose
yhirose merged commit 8710fbd into yhirose:master Oct 26, 2026
27 of 28 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants