T09 · Insecure Skill Coding Practices
- Location
lib/fetcher.js:8- Finding
Arbitrary URL Fetching Enables Server-Side Request Forgery
- Content
View full analysis
Vulnerability Details
File Location:
lib/fetcher.js:8-27(user-controlled source:analyze.js:98-100, 137-141)
Vulnerability Type: Server-Side Request Forgery (SSRF)
Risk Level: HighVulnerable Code
js function fetchUrl(targetUrl) { return new Promise((resolve, reject) => { let redirected = false; const lib = targetUrl.startsWith('https') ? https : http; const req = lib.get(targetUrl, { headers: { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Language': 'en-US,en;q=0.5', 'Connection': 'keep-alive', } }, res => { // Follow up to 3 redirects if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) { if (redirected) { reject(new Error('Too many redirects')); return; } redirected = true; const next = new URL(res.headers.location, targetUrl).toString(); fetchUrl(next).then(resolve).catch(reject); return; }The caller passes the command-line argument directly into this function:
js async function stage1(url) { process.stdout.write('🔍 Fetching article...\n'); const raw=await fetchUrl(url);js const[,,cmd,...args]=process.argv; if(!cmd){console.error('Usage: node analyze.js <url>\n node analyze.js --final');process.exit(1);} let out; if(cmd==='--final') out=await stage3(args[0]?JSON.parse(args[0]):undefined); else out=await stage1(cmd);Technical Analysis
The Skill performs an outbound request to a fully user-controlled URL without validating its scheme, destination hostname, resolved IP address, or network range. There is no protection against loopback, private, link-local, reserved, or cloud metadata addresses.
Red ...[truncated 1865 chars]
- Remediation
View remediation
Remediation Suggestions
- Parse every input with
new URL()and reject malformed URLs. - Allow only the exact
http:andhttps:schemes. - Resolve the hostname before connecting and reject all loopback, private, link-local, multicast, unspecified, reserved, and documentation ranges for IPv4 and IPv6.
- Explicitly block cloud metadata destinations, including link-local metadata addresses and environment-specific metadata hostnames.
- Revalidate the scheme, hostname, and resolved addresses after every redirect.
- Protect against DNS rebinding by ensuring the validated address is the address used for the connection.
- Prefer a domain allowlist when the intended use is limited to known news sources.
- Run the fetch component in a network sandbox that cannot reach internal services or metadata endpoints.
- Record security-safe destination audit logs without exposing credentials or sensitive query parameters.
- Parse every input with
