fix(security): use relpath containment instead of startswith to prevent prefix-collision bypass #11217

Closed
HAL9000 wants to merge 8 commits from fix-7478-startswith-bypass into master

8 Commits

Author SHA1 Message Date
drew 8a87414206 Revert "test(security): add @tdd_issue_7478 BDD regression for path containment bypass"
CI / lint (pull_request) Successful in 57s
CI / typecheck (pull_request) Successful in 1m11s
CI / security (pull_request) Successful in 1m11s
CI / quality (pull_request) Successful in 1m12s
CI / build (pull_request) Successful in 36s
CI / helm (pull_request) Successful in 32s
CI / push-validation (pull_request) Successful in 30s
CI / integration_tests (pull_request) Failing after 4m48s
CI / unit_tests (pull_request) Failing after 5m55s
CI / coverage (pull_request) Has been skipped
CI / docker (pull_request) Has been skipped
CI / status-check (pull_request) Failing after 3s
This reverts commit b5361da2a5.
2026-05-27 20:19:14 -04:00
HAL9000 b5361da2a5 test(security): add @tdd_issue_7478 BDD regression for path containment bypass
CI / push-validation (pull_request) Successful in 25s
CI / helm (pull_request) Successful in 31s
CI / build (pull_request) Successful in 38s
CI / lint (pull_request) Successful in 47s
CI / quality (pull_request) Successful in 50s
CI / typecheck (pull_request) Successful in 1m5s
CI / security (pull_request) Successful in 1m25s
CI / integration_tests (pull_request) Failing after 3m22s
CI / unit_tests (pull_request) Failing after 4m33s
CI / coverage (pull_request) Has been skipped
CI / docker (pull_request) Has been skipped
CI / status-check (pull_request) Failing after 3s
Add Behave BDD scenarios verifying that _is_under() in path_mapper.py
correctly rejects prefix-collision sibling paths and parent traversal,
and accepts legitimate child paths and the root itself.

The four scenarios cover:
- Sibling directory sharing a name prefix (/tmp/sandboxmalicious vs /tmp/sandbox)
- Legitimate child path (/tmp/sandbox/subdir/file.txt)
- Root path itself (/tmp/sandbox == /tmp/sandbox)
- Parent traversal via dot-dot (/tmp/sandbox/../secret.txt)

ISSUES CLOSED: #7478
2026-05-27 18:18:12 -04:00
controller-ci-rerun 2837fde7d0 chore: re-trigger CI [controller]
CI / push-validation (pull_request) Successful in 37s
CI / helm (pull_request) Successful in 42s
CI / build (pull_request) Successful in 48s
CI / lint (pull_request) Successful in 1m4s
CI / quality (pull_request) Successful in 1m31s
CI / typecheck (pull_request) Successful in 1m37s
CI / security (pull_request) Successful in 1m38s
CI / integration_tests (pull_request) Failing after 4m26s
CI / unit_tests (pull_request) Failing after 4m52s
CI / coverage (pull_request) Has been skipped
CI / docker (pull_request) Has been skipped
CI / status-check (pull_request) Failing after 3s
2026-05-27 09:32:09 -04:00
HAL9000 ec72fcd1ac fix(docs): replace non-breaking hyphen in docstring to pass lint
CI / push-validation (pull_request) Successful in 46s
CI / helm (pull_request) Successful in 52s
CI / build (pull_request) Successful in 1m17s
CI / lint (pull_request) Successful in 1m44s
CI / quality (pull_request) Successful in 1m44s
CI / typecheck (pull_request) Successful in 2m6s
CI / security (pull_request) Successful in 2m5s
CI / integration_tests (pull_request) Successful in 3m40s
CI / unit_tests (pull_request) Failing after 6m37s
CI / coverage (pull_request) Has been skipped
CI / docker (pull_request) Has been skipped
CI / status-check (pull_request) Failing after 3s
The RUF002 rule flagged a non-breaking hyphen (U+2011) in the
_relative_to() docstring. Replaced with regular hyphen for clean CI.
2026-05-17 18:39:19 +00:00
HAL9000 3af59f95ab fix(security): use posixpath.relpath in _relative_to to prevent prefix-collision bypass
CI / push-validation (pull_request) Successful in 48s
CI / helm (pull_request) Successful in 51s
CI / build (pull_request) Successful in 1m8s
CI / lint (pull_request) Failing after 1m19s
CI / typecheck (pull_request) Successful in 1m59s
CI / quality (pull_request) Successful in 1m58s
CI / security (pull_request) Successful in 2m6s
CI / integration_tests (pull_request) Successful in 4m43s
CI / unit_tests (pull_request) Failing after 6m43s
CI / docker (pull_request) Has been skipped
CI / coverage (pull_request) Has been skipped
CI / status-check (pull_request) Failing after 5s
Replace naive string-slicing (path[len(root)+1:]) with canonical
posixpath.relpath() for relative-path extraction, consistent with
_is_under relpath-based containment check. Prevents prefix-collision
path-traversal where an attacker filename is a literal string-prefix of
the sandbox root (issue #7478).
2026-05-17 04:49:21 +00:00
HAL9000 db50d039d6 fix(security): restore posixpath containment checks in path_mapper.py
CI / helm (pull_request) Successful in 35s
CI / lint (pull_request) Successful in 1m8s
CI / build (pull_request) Successful in 1m11s
CI / quality (pull_request) Successful in 1m40s
CI / security (pull_request) Successful in 1m41s
CI / typecheck (pull_request) Successful in 1m45s
CI / push-validation (pull_request) Successful in 18s
CI / integration_tests (pull_request) Successful in 5m4s
CI / unit_tests (pull_request) Successful in 5m54s
CI / docker (pull_request) Successful in 1m33s
CI / coverage (pull_request) Successful in 12m8s
CI / status-check (pull_request) Successful in 2s
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 06:36:35 +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