fix(UNSAFE_TOOL_OUTPUT_PATH): resolve path traversal before matching system dirs#31
Open
dmchaledev wants to merge 1 commit into
Open
fix(UNSAFE_TOOL_OUTPUT_PATH): resolve path traversal before matching system dirs#31dmchaledev wants to merge 1 commit into
dmchaledev wants to merge 1 commit into
Conversation
The rule matched outputPath against system directories by literal prefix, so a traversal payload with a benign-looking prefix bypassed it: outputPath: "/var/app/../../etc/passwd" -> resolves to /etc/passwd but reported 0 findings / PASSED, since the string starts with "/var". For a CI security gate this is a false negative that lets a tool write to a sensitive system path undetected. Normalize the path (POSIX `.`/`..` collapse) before comparing, so the check judges where the path actually lands. Evidence and description now surface both the literal and resolved path when traversal changes it. Traversal that stays inside a safe directory still passes. Adds regression tests for traversal into /etc and /proc, redundant same-dir traversal, and a safe-directory traversal no-op. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TVtRsWmF1TvpgQbZ9AzsrC
5 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A CRITICAL-severity false negative in the
UNSAFE_TOOL_OUTPUT_PATHrule: a tool whoseoutputPathuses path traversal to escape a benign-looking prefix into a sensitive system directory is not flagged, so the scanner reportsPASSEDon a config that lets a tool write to/etc/passwd.The rule (
src/rules/injection-rules.ts) matchedoutputPathagainst the system-directory list by literal prefix:A traversal payload that starts with a safe-looking prefix never matches, even though it resolves into a system path.
Repro (built CLI at current
main)The same bypass applies to deeper payloads (verified against the built CLI):
outputPath/etc/passwd/etc/passwd/etc/../etc/passwd/etc/passwd/var/app/../../etc/shadow/etc/shadow/app/data/../../../proc/self/mem/proc/self/mem/app/tmp/../data/output.json/app/data/output.jsonFor a tool sold as a CI/CD security gate, a write target that lands in
/etcor/procslipping through unflagged is a meaningful bypass — exactly the class of issue this rule exists to catch.Fix
Normalize the path (POSIX
./..collapse) before comparing against the system-directory list, so the check judges where the path actually lands rather than its literal prefix. The existing exact-match / prefix-boundary logic (and the#8false-positive guards for/etcfoo,/rootfs, etc.) is preserved — it now just runs on the resolved path. When traversal changes the path, the finding'sdescriptionandevidencesurface both the literal and the resolved form so the bypass is visible:Traversal that stays inside a safe directory (
/app/tmp/../data/output.json→/app/data/output.json) still produces no finding — no new false positives.The change is localized to the
UNSAFE_TOOL_OUTPUT_PATHrule; no other rule, the parser, or the report shape is touched. POSIX semantics are used regardless of host OS because these directories (/etc,/proc, …) are POSIX paths.Verification
npm run typecheck✓ ·npm run lint(0 warnings) ✓ ·npm test— 122 passed, 5 suites ✓ ·npm run build✓scanner.test.ts: traversal into/etcand/proc, redundant same-dir traversal (/etc/../etc/passwd), and a safe-directory-traversal no-op.Why this isn't a duplicate
#8("UNSAFE_TOOL_OUTPUT_PATH false positive on prefix boundaries") fixed a false positive on thedir + '/'boundary; this fixes a false negative via traversal — complementary, and the boundary guards remain green. None of the open issues (#11, #19, #26, #27) or open PRs (secrets #28/#29, TLS #18,--rule#17/#25, docs, CI #12/#20) touch output-path normalization.Acceptance criteria
outputPaththat resolves into a system directory produces a CRITICAL finding.🤖 Generated with Claude Code
https://claude.ai/code/session_01TVtRsWmF1TvpgQbZ9AzsrC
Generated by Claude Code