Skip to content

fix: prevent path traversal via prefix collision in containment check#62

Open
nezukoagent wants to merge 1 commit into
ember-cli:masterfrom
nezukoagent:fix/path-traversal-prefix-collision
Open

fix: prevent path traversal via prefix collision in containment check#62
nezukoagent wants to merge 1 commit into
ember-cli:masterfrom
nezukoagent:fix/path-traversal-prefix-collision

Conversation

@nezukoagent
Copy link
Copy Markdown

Summary

The path containment check uses indexOf() which only verifies string prefix, not directory boundary. This allows attackers to escape the output directory via prefix collision.

The Bug

// response-header.js:59
if (filename.indexOf("\0") !== -1 || filename.indexOf(outputPath) !== 0) {

indexOf() returns 0 if outputPath appears at the start, but doesn't check directory boundaries:

  • outputPath = "/tmp/build"
  • filename = "/tmp/buildcache/secret/keys.txt"
  • filename.indexOf(outputPath) === 0 → true → BYPASSES CHECK!

PoC

GET /..%2fbuildcache%2fsecret%2fkeys.txt HTTP/1.1
→ path.join("/tmp/build", "/../buildcache/secret/keys.txt") = "/tmp/buildcache/secret/keys.txt"
→ indexOf("/tmp/build") = 0 → passes check
→ reads /tmp/buildcache/secret/keys.txt

Fix

Use startsWith() with trailing path separator:

const normalizedOutput = outputPath.endsWith(path.sep) ? outputPath : outputPath + path.sep;
if (filename.indexOf("\0") !== -1 || (!filename.startsWith(normalizedOutput) && filename !== outputPath)) {

References

The previous check used indexOf(outputPath) !== 0 which only verifies
the path STARTS WITH the output directory string, not that it's actually
CONTAINED within it. This allows prefix collision attacks:

  outputPath = '/tmp/build'
  filename = '/tmp/buildcache/secret/keys.txt'
  filename.indexOf(outputPath) === 0  // true - BYPASSES CHECK!

Fix: Use startsWith() with trailing path separator to ensure proper
directory boundary validation.

Fixes: GHSA-27hx-7875-xvvh
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.

1 participant