T09 · Insecure Skill Coding Practices
- Location
assets/main_handler.js:80- Finding
Unrestricted URL Retrieval Enables Server-Side Request Forgery
- Content
View full analysis
Vulnerability Details
File Location:
assets/main_handler.js:10-11, 80-83; also present inassets/youtube_handler.js:3-4, 32
Vulnerability Type: Server-Side Request Forgery through unrestricted browser navigation
Risk Level: HighVulnerable Code
javascript const targetUrl = process.argv[2]; const videoId = targetUrl?.split('v=')[1]?.split('&')[0]; const mode = targetUrl?.includes('youtube.com') ? 'YOUTUBE' : 'GENERIC';javascript } else { // Generic dynamic page scraping await page.goto(targetUrl, { waitUntil: 'networkidle' }); const title = await page.title(); const content = await page.evaluate(() => document.body.innerText); console.log(JSON.stringify({ status: 'SUCCESS', type: 'GENERIC', title, data: content.substring(0, 10000) })); }The dedicated YouTube handler also navigates directly to an unvalidated argument:
javascript const targetUrl = process.argv[2]; const videoId = targetUrl.split('v=')[1]?.split('&')[0];javascript await page.goto(targetUrl, { waitUntil: 'networkidle' });Technical Analysis
The application accepts a URL directly from the command line and passes it to Playwright without validating its protocol, hostname, port, resolved IP address, or redirect destinations. The generic handler then reads the response body and prints up to 10,000 characters to standard output.
Consequently, the browser can be directed to resources reachable from the container but not necessarily reachable by the party supplying the URL. Potential destinations include loopback interfaces, private network ranges, link-local services, internal administration panels, and cloud instance metadata endpoints.
Checking whether the input contains
youtube.comis not a security boundary. Generic URLs receive no destination restrictions, and substring matching does not establish tha ...[truncated 1274 chars]- Remediation
View remediation
Remediation Suggestions
- Parse input with the standard
URLclass and allow only explicitly required schemes, normallyhttps:and optionallyhttp:. - Reject URLs containing credentials, unsupported ports, malformed hostnames, or noncanonical representations.
- Resolve the destination hostname and reject every address in loopback, private, link-local, multicast, reserved, unspecified, carrier-grade NAT, and cloud metadata ranges for both IPv4 and IPv6.
- Explicitly block metadata endpoints such as
169.254.169.254and their IPv6 or provider-specific equivalents. - Disable automatic redirects or independently validate every redirect destination before following it.
- Protect against DNS rebinding by validating the address actually used for the connection, not only an earlier DNS lookup.
- Prefer a strict hostname allowlist if the skill only needs to support known public services.
- Apply outbound network controls at the container or host firewall layer so the browser cannot reach private networks or metadata services.
- Validate YouTube origins using exact parsed hostnames rather than substring matching, and validate the video identifier with the expected format.
- Add automated tests covering loopback, private IPv4, IPv6 loopback, link-local addresses, alternate numeric IP encodings, redirect chains, and DNS rebinding scenarios.
- Parse input with the standard
