T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/scrape.js:15
- Finding
- Unrestricted Browser Navigation Enables Server-Side Request Forgery<![CDATA[ ## Vulnerability Details **File Location**: `scripts/scrape.js:15-40`, `scripts/crawl.js:15-50`, and `scripts/screenshot.js:16-42` **Vulnerability Type**: Server-Side Request Forgery through unvalidated browser navigation **Risk Level**: High ### Vulnerable Code `scripts/scrape.js:15-40`: ```javascript const url = process.argv[2]; const selector = process.argv[3] || 'body'; if (!url) { console.error('Usage: node scrape.js <url> [selector]'); console.error('Example: node scrape.js https://example.com h2'); process.exit(1); } (async () => { const browser = await puppeteer.launch({ headless: 'new', args: ['--no-sandbox', '--disable-setuid-sandbox'] }); const page = await browser.newPage(); // Set a neutral user agent await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'); console.error(`Fetching: ${url}`); await page.goto(url, { waitUntil: 'networkidle2', timeout: 30000 }); ``` `scripts/crawl.js:15-50`: ```javascript const url = process.argv[2]; const selector = process.argv[3]; const maxPages = parseInt(process.argv[4]) || 10; if (!url || !selector) { console.error('Usage: node crawl.js <url> <selector> [maxPages]'); console.error('Example: node crawl.js https://example.com/products .item 5'); process.exit(1); } (async () => { const browser = await puppeteer.launch({ headless: 'new', args: ['--no-sandbox', '--disable-setuid-sandbox'] }); const page = await browser.newPage(); // Set a neutral user agent await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'); let allData = []; for (let i = 1; i <= maxPages; i++) { // Build page URL - append ?page=X or &page=X let pageUrl = url; if (i > 1) { pageUrl = url.includes('?') ? `${url}&page=${i}` : `${url}?page=${i}`; } console.error(`[${i}/ ...[truncated 3321 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Accept only explicitly supported protocols, preferably `https:` and, where necessary, `http:`. 2. Reject URLs containing embedded credentials or malformed hostnames. 3. Resolve the hostname before navigation and reject every address in loopback, private, link-local, multicast, reserved, and cloud-metadata ranges for both IPv4 and IPv6. 4. Validate all addresses returned by DNS, not only the first result. 5. Revalidate the destination after every redirect. Consider disabling automatic redirects and processing each `Location` header through the same policy. 6. Use an explicit hostname allowlist when the intended scraping targets are known. 7. Run the browser in a network-isolated environment that cannot route to internal services or metadata endpoints. 8. Apply egress firewall rules as a second enforcement layer. 9. Add tests covering IPv4, IPv6, alternative address notation, redirects, DNS rebinding, internal DNS names, and metadata addresses. 10. Ensure URL validation and the actual connection use consistent DNS results to reduce time-of-check/time-of-use bypasses. ]]>
