Skip to content

FIX Detect URL-encoded null bytes after the target in PathTraversalOutputScorer - #3943

Open
Shivam Sharma (ShivamSharma43) wants to merge 2 commits into
microsoft:mainfrom
ShivamSharma43:fix/path-traversal-null-byte
Open

Shivam Sharma (ShivamSharma43) wants to merge 2 commits into
microsoft:mainfrom
ShivamSharma43:fix/path-traversal-null-byte

Conversation

@ShivamSharma43

Copy link
Copy Markdown
Contributor

Description

Fixes #3942.

PathTraversalOutputScorer scored ../../../etc/passwd%00.png as False, but scored the same payload with a literal NUL (passwd\x00.png) as True. The end-of-name lookahead _FILE_END rejected every percent escape after the sensitive file name (%(?:25)?[0-9a-f]{2}). That check is there so that .env%41 (decodes to .envA) is not taken for .env. It also caught %00 and %2500, which decode to a NUL. A NUL is not part of the name: a file API that reads the path as a C string stops there and opens /etc/passwd.

The fix leaves the encoded NUL out of the rejected escapes: %(?!(?:25)?00)(?:25)?[0-9a-f]{2}. %41, %2541, %2e and %252e after the name are still rejected, so the existing .envA and .env.example negatives are unchanged. The class docstring now says that a null byte after the target, literal or encoded, is accepted.

Tests and Documentation

New cases in test_path_traversal_detected (tests/unit/score/regex/test_path_traversal_output_scorer.py):

  • ../../../etc/passwd%00 and ../../../etc/passwd%00.png
  • ..%2f..%2fetc%2fpasswd%00.png (fully encoded)
  • ../../../etc/passwd%2500.jpg (double-encoded)
  • ../../.env%00.txt
  • ../../../etc/passwd\x00.png (literal NUL, already detected on main; kept as a control)

The five encoded cases fail on main (699931d) and pass with the fix. All of tests/unit/score/regex passes (1954 tests). ruff check, ruff format --check and ty check are clean on the changed files.

No documentation changes beyond the docstring. I didn't run JupyText because no notebooks are affected.

This change was prepared with the help of Claude Code (an AI coding assistant). I reviewed the change and the tests.

🤖 Generated with Claude Code

…tputScorer

The end-of-name check rejected every percent escape after the sensitive file
name, so ../../../etc/passwd%00.png and its double-encoded form scored False
while the same payload with a literal NUL scored True. An encoded NUL is not a
file suffix: it ends the name once a C-string file API decodes it. Other
escapes such as %41 and %2541 are still rejected.

Fixes microsoft#3942

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings November 4, 2026 12:39

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

BUG: PathTraversalOutputScorer misses URL-encoded null-byte payloads such as ../../../etc/passwd%00.png

2 participants