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

Merged
HAL9000 merged 2 commits from security/relpath-containment-fallback into master 2026-06-18 22:42:36 +00:00
+2 -1
View File
2
@@ -263,7 +263,8 @@ class InlineToolExecutor:
try:
resolved = Path(value).resolve()
Review

BLOCKING: This security fix is bundled with 860+ lines of unrelated deletions across 19 files. Per atomic commit rule, must be separate PRs.

BLOCKING: This security fix is bundled with 860+ lines of unrelated deletions across 19 files. Per atomic commit rule, must be separate PRs.
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(".."):
Outdated
Review

BLOCKING — Missing regression test: The existing path validation tests use /etc/passwd which fails regardless of implementation. Add a specific test that creates a sibling directory with a prefix-collision name (e.g., sandbox=/tmp/inline-sandbox, attacker=/tmp/inline-sandboxx/evil) to verify the relpath-based check correctly rejects it. This is especially critical for security fixes. Per CONTRIBUTING.md, all bug fixes require a regression test.

BLOCKING — Missing regression test: The existing path validation tests use /etc/passwd which fails regardless of implementation. Add a specific test that creates a sibling directory with a prefix-collision name (e.g., sandbox=/tmp/inline-sandbox, attacker=/tmp/inline-sandboxx/evil) to verify the relpath-based check correctly rejects it. This is especially critical for security fixes. Per CONTRIBUTING.md, all bug fixes require a regression test.
Outdated
Review

Suggestion: Consider adding a more descriptive variable name than rel for the relative path result. E.g., rel_path would more clearly indicate the semantic purpose at the call site. Not blocking.

Suggestion: Consider adding a more descriptive variable name than `rel` for the relative path result. E.g., `rel_path` would more clearly indicate the semantic purpose at the call site. Not blocking.
return (
f"Path '{value}' for key '{key}' escapes sandbox "
f"root '{sandbox_path}'"