# Escaping well-configured VSCode extensions (for profit)

VSCode Webview localResourceRoots bypass via %2f-decoded path traversal lets JS-executing attacker read arbitrary filesystem files.

- Payout: $7,500
- Severity: high
- Program: Microsoft
- Credited: Vasco Franco
- Disclosed: 2023-02-23
- CVE: CVE-2022-41042
- Write-up quality: 8/10
- Original: https://blog.trailofbits.com/2023/02/23/escaping-well-configured-vscode-extensions-for-profit/
- Library page: https://bugbountylibrary.com/r/blog%3Ablog-trailofbits-com-2023-02-23-escaping-well-configured-vscode-extensions-for-profit
- Tags: domain:desktop impact:data-leak kind:bounty platform:blog sev:high tech:chromium tech:electron technique:js-analysis technique:parser-differential technique:source-review vuln:path-traversal

**Target:** VSCode Webview resource loader (vscode-resource.vscode-cdn.net)
**Root cause:** VSCode decodes the URL path with decodeURIComponent after the browser normalized it, then checks containment with resourceFsPath.startsWith(rootPath) without re-normalizing, so ../ sequences introduced via %2f pass the root check.
**Steps:**
1. Get JS execution in a Webview with CSP connect-src including .vscode-resource.vscode-cdn.net
2. Fetch `https://file+.vscode-resource.vscode-cdn.net/[valid-root]/%2f..%2f..%2f..%2f..%2f..%2fetc%2fpasswd`
3. Service worker converts request to postMessage('load-resource') to main thread
4. VSCode decodeURIComponent decodes %2f to /, introducing ../ after browser normalization
5. containsResource startsWith(rootPath) passes; file read and returned
**How found:** After exploiting misconfigured extensions, hypothesized VSCode itself could be bypassed; tried path traversal payloads, observed browser normalized /.. but %2f.. survived, then traced service worker postMessage flow to decodeURIComponent and unnormalized startsWith.
**Exploitation:** With JS execution in a Webview, add link tags/fetch to the fake vscode-resource domain using %2f-encoded traversal; exfiltrate file contents via DNS prefetch to attacker domain.
**Insight:** When a browser normalizes a URL before app code sees it, look for any later decodeURIComponent/percent-decoding that reintroduces ../ after normalization; test %2f-encoded traversal against startsWith-style root checks.
