T09 · Insecure Skill Coding Practices
- Location
scripts/repurpose.js:33- Finding
Arbitrary URL Fetching Enables Server-Side Request Forgery
- Content
View full analysis
Vulnerability Details
File Location:
scripts/repurpose.js, lines 33-43; invocation at lines 178-181
Vulnerability Type: Server-Side Request Forgery (SSRF)
Risk Level: HighVulnerable Code
js function httpGet(url) { return new Promise((resolve, reject) => { const u = new URL(url); const mod = u.protocol === 'https:' ? https : require('http'); mod.get(url, { headers: { 'User-Agent': 'Mozilla/5.0' } }, res => { let d = ''; res.on('data', c => d += c); res.on('end', () => resolve(d)); }).on('error', reject); }); }The user-controlled URL reaches the function here:
js if (args.url) { console.log(`🔗 Fetching ${args.url}...`); const html = await httpGet(args.url); content = extractText(html); }Technical Analysis
The
--urlcommand-line argument is passed directly tohttpGet. The implementation does not apply a hostname allowlist, resolve and validate destination IP addresses, or reject loopback, private, link-local, and reserved network ranges. It also lacks connection and response timeouts and does not impose a response-size limit.Consequently, anyone able to control the command-line argument can instruct the process to issue HTTP requests from the host on which the skill runs. The request therefore inherits that host's network reachability and may access endpoints that are unavailable to an external attacker.
The response is passed through
extractTextand subsequently submitted to OpenAI or Anthropic. This creates a potential secondary disclosure path in which information retrieved from an internal endpoint is transmitted to an external LLM service.Attack Path
- An attacker or untrusted caller supplies a URL such as a loopback address, private network host, or cloud link-local metadata endpoint through
--url. parseArgsstores the value inargs.url.mainpasses the value directly tohttpGet...[truncated 1028 chars]
- An attacker or untrusted caller supplies a URL such as a loopback address, private network host, or cloud link-local metadata endpoint through
- Remediation
View remediation
Remediation Suggestions
- Accept only explicitly supported protocols, preferably HTTPS.
- Use an explicit allowlist of trusted source domains where operationally possible.
- Resolve the hostname before connecting and reject every address in loopback, private, link-local, multicast, unspecified, and reserved ranges for both IPv4 and IPv6.
- Ensure the validated IP is the address used for the connection to reduce DNS-rebinding and time-of-check/time-of-use risks.
- If redirect support is later added, validate the protocol, hostname, and resolved destination again for every redirect.
- Apply strict connection, read, and total-request timeouts.
- Enforce a maximum response size while streaming rather than collecting an unlimited response before truncating extracted text.
- Restrict accepted content types to expected textual formats.
- Run the skill in a sandbox with outbound network restrictions that block internal and metadata networks.
- Warn users before externally transmitting fetched content and avoid sending sensitive internal data to LLM providers.
