T09 · Insecure Skill Coding Practices
Error
- Location
- src/converter.js:219
- Finding
- Unrestricted URL Fetching Enables Server-Side Request Forgery## Vulnerability Details **File Location**: `bin/cli.js:69-71`, `bin/cli.js:110-112`, and `src/converter.js:219-225` **Vulnerability Type**: Server-Side Request Forgery **Risk Level**: High The blog conversion commands accept an arbitrary value beginning with `http` and pass it directly to an unrestricted Axios request. ```javascript // bin/cli.js:69-71 if (source.startsWith('http')) { console.log('📥 Fetching blog content...'); content = await converter.fetchBlogContent(source); } ``` The same behavior is present in the LinkedIn conversion command: ```javascript // bin/cli.js:110-112 if (source.startsWith('http')) { console.log('📥 Fetching blog content...'); content = await converter.fetchBlogContent(source); } ``` The destination is fetched without validating its host, resolved IP address, port, or redirect chain: ```javascript // src/converter.js:219-225 async fetchBlogContent(url) { try { const response = await axios.get(url, { headers: { 'User-Agent': 'Mozilla/5.0' }, timeout: 10000 }); ``` ### Technical Analysis Checking only whether a value starts with `http` is not a security boundary. The code does not parse the URL using a strict URL parser or limit requests to public blog hosts. Consequently, callers can request loopback, private-network, link-local, or cloud metadata destinations. Axios also follows redirects by default. An initially public URL can therefore redirect to an internal destination unless every redirect target is independently validated. The timeout limits request duration but does not prevent access to sensitive network locations. No response-size limit is configured either, allowing a hostile endpoint to return an excessively large body. The fetched response is parsed as article content and then supplied to the OpenAI transformation method. This can cause information obtained from an internal service to leave the local environment ...[truncated 1510 chars]
- Remediation
- ## Remediation Suggestions - Parse destinations with the standard `URL` class and permit only explicit `http:` and `https:` protocols. - Reject URLs containing credentials, ambiguous host representations, or unsupported ports. - Resolve the hostname before connecting and reject loopback, private, link-local, multicast, reserved, and cloud metadata address ranges for both IPv4 and IPv6. - Disable automatic redirects or validate the scheme, hostname, resolved address, and port of every redirect target. - Prefer an explicit allowlist of trusted blog domains when the deployment permits it. - Set conservative `maxContentLength` and `maxBodyLength` limits. - Restrict response content types to expected textual or HTML formats. - Run network fetching in a sandbox with no access to internal services or metadata endpoints. - Require explicit user confirmation before transferring fetched content to OpenAI. - Add tests covering loopback addresses, private IP addresses, IPv6 literals, alternative numeric IP representations, DNS rebinding, and redirect-based bypasses.
