Compare commits

...

3 Commits

Author SHA1 Message Date
HAL9000 018e42bb8c fix(security): restore posixpath containment checks in path_mapper.py
Remove unused import os that triggers lint/typecheck failures and
replace os.path.relpath() usage with posixpath.relpath() throughout
path_mapper.py. Container paths are always POSIX — mixing os.path breaks
cross-platform correctness for non-POSIX hosts and was the sole functional
change on this PR branch (the actual security fix was already merged to master).

All reviewers flagged: unused import (ci/lint), wrong import domain
(ci/typecheck, ci/quality), and mismatch with master's posixpath-only
implementation.

Closes #7478
Refs: #11217
2026-05-16 13:50:09 +00:00
HAL9000 b0db5d715f fix(security): replace startswith-based _is_under/_relative_to with os.path.relpath containment (#7478)
CI / push-validation (pull_request) Successful in 44s
CI / helm (pull_request) Successful in 46s
CI / lint (pull_request) Successful in 1m15s
CI / build (pull_request) Successful in 1m4s
CI / security (pull_request) Successful in 1m59s
CI / unit_tests (pull_request) Successful in 5m4s
CI / integration_tests (pull_request) Failing after 11m49s
CI / quality (pull_request) Failing after 11m54s
CI / typecheck (pull_request) Failing after 11m57s
CI / coverage (pull_request) Has been cancelled
CI / docker (pull_request) Has been cancelled
CI / status-check (pull_request) Has been cancelled
The existing implementation in posixpath used relpath for containment but
still compared the result string via startswith. This is vulnerable to
prefix-collision attacks where an attacker's name is a prefix of the sandbox
root.

This commit replaces both _is_under and _relative_to with full canonical
relpath-based logic using os.path.relpath, consistent with the security
specification.
2026-05-15 18:35:17 +00:00
HAL9000 ca44dd48b3 fix(security): use relpath containment instead of startswith to prevent prefix-collision bypass
CI / push-validation (pull_request) Successful in 38s
CI / helm (pull_request) Successful in 45s
CI / lint (pull_request) Failing after 1m20s
CI / build (pull_request) Successful in 1m11s
CI / quality (pull_request) Successful in 1m28s
CI / typecheck (pull_request) Successful in 2m2s
CI / security (pull_request) Successful in 1m58s
CI / integration_tests (pull_request) Successful in 4m7s
CI / unit_tests (pull_request) Successful in 7m2s
CI / coverage (pull_request) Has been skipped
CI / docker (pull_request) Has been skipped
CI / status-check (pull_request) Failing after 3s
2026-05-15 08:40:45 +00:00
+2 -1
View File
@@ -263,7 +263,8 @@ class InlineToolExecutor:
try:
resolved = Path(value).resolve()
sandbox_resolved = sandbox_path.resolve()
if not str(resolved).startswith(str(sandbox_resolved)):
rel = os.path.relpath(str(resolved), str(sandbox_resolved))
if rel.startswith(".."):
return (
f"Path '{value}' for key '{key}' escapes sandbox "
f"root '{sandbox_path}'"