From cb3d1f2714ab05e8dc550addb52d8c9a47ed58f0 Mon Sep 17 00:00:00 2001 From: "Claude Opus 4.8 (1M context)" Date: Sat, 4 Jul 2026 23:48:50 +0200 Subject: [PATCH] fix(library): reject Windows drive-letter paths in _resolve_dlc_path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 '/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) --- server.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/server.py b/server.py index 708fac0..2e19435 100644 --- a/server.py +++ b/server.py @@ -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 `/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 —