T09 · Insecure Skill Coding Practices
- Location
SKILL.md:611- Finding
Unauthenticated Server-Side Request Forgery in Crawler Web Server Example
- Content
View full analysis
{ const url = new URL(req.url, 'http://localhost').searchParams.get('url'); const crawler = new CheerioCrawler({ maxRequestsPerCrawl: 1, async requestHandler({ $ }) { res.end(JSON.stringify({ title: $('title').text() })); }, }); await crawler.run([url]); }); server.listen(3000); ``` ### Technical Analysis The HTTP server takes the `url` query parameter from an incoming request and passes it directly to `crawler.run()` without validating its scheme, hostname, resolved IP address, port, or redirect destination. Because the crawler makes the request from the server's network context, a remote client could make it connect to resources that are inaccessible from the client's own network. Potential destinations include: - Loopback services such as `127.0.0.1` - Private network ranges - Link-local services - Cloud instance metadata endpoints - Internal administrative interfaces - Services on otherwise inaccessible ports The example also calls `server.listen(3000)` without specifying a loopback address. In Node.js, this commonly binds the server to all available interfaces, potentially exposing the endpoint to other hosts. Although the response only returns the fetched page's HTML title, this still provides a content and timing oracle. More importantly, the outbound GET request itself may trigger actions on internal services that incorrectly use GET requests for state changes. Redirects must also be validated. Validating only the initial hostname would not prevent an allowed public URL from redirecting the crawler to a private address. ### Attack Path 1. A user deploys the do ...[truncated 1449 chars]- Remediation
View remediation
