T05 · Unauthorized Access and Privilege Escalation
Error
- Location
- scripts/playwright-simple.js:11
- Finding
- Unrestricted URL Navigation Enables Server-Side Request Forgery<![CDATA[ ## Vulnerability Details **File Location**: `scripts/playwright-simple.js:11-14, 32`; `scripts/playwright-stealth.js:22-30, 86-90` **Vulnerability Type**: Server-Side Request Forgery (SSRF) through unrestricted browser navigation **Risk Level**: High ### Vulnerable Code ```javascript // scripts/playwright-simple.js const url = process.argv[2]; const waitTime = parseInt(process.env.WAIT_TIME || '3000'); const screenshotPath = process.env.SCREENSHOT_PATH; await page.goto(url, { waitUntil: 'domcontentloaded' }); ``` ```javascript // scripts/playwright-stealth.js const url = process.argv[2]; const waitTime = parseInt(process.env.WAIT_TIME || '5000'); const headless = process.env.HEADLESS !== 'false'; const screenshotPath = process.env.SCREENSHOT_PATH || `./screenshot-${Date.now()}.png`; const saveHtml = process.env.SAVE_HTML === 'true'; const response = await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 30000, }); ``` ### Technical Analysis Both scraper implementations accept a URL directly from the command line and pass it to Playwright without validating its scheme, destination address, hostname, DNS resolution, or redirects. Because the browser executes from the host running the Skill, it can reach services available to that host rather than only services reachable by the remote caller. This may include: - Loopback services such as `127.0.0.1` and `[::1]` - Private network ranges - Link-local services - Cloud instance metadata endpoints such as `169.254.169.254` - Internal administrative applications - Destinations reached after an initially permitted URL redirects to a restricted address The returned page text, extracted links, screenshots, and optional HTML files can expose responses from those internal destinations. ### Attack Path 1. An attacker or untrusted workflow supplies an internal URL as the scraper's positional argument. 2. The script passes the URL directly to `page.goto`. 3. Chromium sends the request using ...[truncated 794 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Accept only explicitly supported schemes, normally `https:` and optionally `http:`. 2. Resolve the destination hostname before navigation and reject loopback, private, link-local, multicast, reserved, and unspecified IP ranges for both IPv4 and IPv6. 3. Explicitly block cloud metadata endpoints, including `169.254.169.254`. 4. Validate every redirect target rather than validating only the initial URL. 5. Protect against DNS rebinding by comparing validated addresses with the addresses used for connections. 6. Prefer a domain allowlist when the intended scraping targets are known. 7. Restrict browser egress at the firewall or container-network level so application validation is not the only control. 8. Run scraping jobs in an isolated network namespace without access to internal control-plane services. ]]>
