Ensure tree traversal attack is protected against. - #2
Open
ro-savage wants to merge 1 commit into
Open
Conversation
…s-is http://<victim>:3000/../../../../../../home/<user>/.ssh/id_rsa
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.
From Claude:
Vuln 1 — Path Traversal → Arbitrary File Read: src/server.mjs:66-67 (and :20-28)
Description
The static file handler builds a filesystem path by joining the public directory with the raw request path, with no normalization
or containment check:
// src/server.mjs:66
const filePath = url === "/" ? join(PUBLIC, "index.html") : join(PUBLIC, url.slice(1));
await serveStatic(res, filePath); // serveStatic() just readFile()s it, :20-28
url is req.url.split("?")[0] — Node's HTTP server does not collapse ../ dot-segments in req.url, so a request target containing ..
reaches join() verbatim. join(PUBLIC, "../../../../etc/passwd") resolves outside PUBLIC, and serveStatic reads and returns
whatever file results. The MIME map falls back to application/octet-stream for unknown extensions, so extension-less secrets are
served fine.
Exploit Scenario
Browsers normalize ../, but an attacker doesn't use a browser. Against a victim running the tool:
curl --path-as-is http://:3000/../../../../../../etc/passwd
curl --path-as-is http://:3000/../../../../../../home//.ssh/id_rsa
curl --path-as-is http://:3000/../../../../../../home//.aws/credentials
This reads any file the running user can read — SSH keys, cloud credentials, ~/.claude/ auth material, the full transcript corpus,
etc. Combined with Vuln 2 (server binds to all interfaces), this is exploitable by anyone on the same LAN/Wi-Fi, unauthenticated.