fix(library): reject Windows drive-letter paths in _resolve_dlc_path

The new test_absolute_path_rejected pins 'C:/Windows/system32/x' → None, but on
POSIX a drive-letter path isn't absolute, so Path(dlc)/'C:/…' becomes the
contained relative dir '<dlc>/C:/…' and slipped through the lexical containment
check (red on the Linux CI). Not an escape, but the traversal contract should
hold cross-platform (a shared library is reached from either OS). Reject a path
that is absolute or drive-qualified in either POSIX or Windows semantics before
the containment check. Legitimate relative/junction paths are unaffected.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Claude Opus 4.8 (1M context)
2026-07-04 23:48:50 +02:00
parent 0a45e89777
commit cb3d1f2714
+10
View File
@@ -5253,6 +5253,16 @@ def _resolve_dlc_path(dlc: Path, filename: str) -> Path | None:
safe = filename.replace("\\", "/")
if "\x00" in safe:
return None
# Reject drive-letter / absolute paths in BOTH conventions. A POSIX "/x" is
# caught by the containment check below (the `/` operator discards `root`),
# but a Windows drive-absolute "C:/x" is treated as a relative "C:" dir on
# POSIX and would otherwise slip in as `<root>/C:/x` — so the contract must
# hold cross-platform (a shared library is reached from either OS).
from pathlib import PurePosixPath, PureWindowsPath
if (PurePosixPath(safe).is_absolute()
or PureWindowsPath(safe).is_absolute()
or PureWindowsPath(safe).drive):
return None
try:
root = dlc.resolve()
# normpath collapses `.`/`..`/duplicate separators purely lexically —