T09 · Insecure Skill Coding Practices
Error
- Location
- src/converter.js:219
- Finding
- Arbitrary Blog URL Fetching Enables Server-Side Request Forgery## Vulnerability Details **File Location**: `src/converter.js:219-225`; reachable from `bin/cli.js:68-72` and `bin/cli.js:109-113` **Vulnerability Type**: Server-Side Request Forgery (SSRF) **Risk Level**: High ### Vulnerable Code ```javascript async fetchBlogContent(url) { try { const response = await axios.get(url, { headers: { 'User-Agent': 'Mozilla/5.0' }, timeout: 10000 }); ``` The affected CLI commands pass user-controlled URLs directly to this method: ```javascript if (source.startsWith('http')) { console.log('📥 Fetching blog content...'); content = await converter.fetchBlogContent(source); } ``` ### Technical Analysis The `blog-to-twitter` and `blog-to-linkedin` commands accept a user-controlled source. Any value beginning with `http` is submitted to `axios.get()` without validating its scheme, hostname, port, resolved IP address, or redirect destination. A timeout limits request duration but does not restrict where the request can be sent. Consequently, the process can be induced to contact: - Loopback services such as `127.0.0.1` or `::1` - Private-network services - Link-local addresses and cloud instance metadata services - Internal administrative interfaces that are unavailable to the external attacker - Public URLs that redirect to one of these prohibited destinations After retrieval, the response is parsed as page content. For normal conversion operations, up to 8,000 characters of the extracted content are placed in an AI prompt and sent to the configured OpenAI API. Therefore, data obtained through SSRF may be incorporated into generated output or transmitted to the declared external AI provider. Remote URL retrieval is necessary for the documented blog-import feature, but unrestricted access to arbitrary network destinations exceeds the minimum network privileges needed to fetch public blog posts. ### Attack Path 1. An attacker supplies or persu ...[truncated 1255 chars]
- Remediation
- ## Remediation Suggestions 1. Parse input with `new URL()` and reject malformed URLs. 2. Permit only explicitly required schemes, preferably HTTPS. 3. Reject embedded credentials, nonstandard ports, and hostnames not required by the feature. 4. Resolve the destination hostname before connecting and block loopback, private, link-local, multicast, unspecified, and reserved IPv4 and IPv6 ranges. 5. Repeat destination validation after every DNS resolution and for every redirect target. 6. Disable automatic redirects or implement a bounded redirect handler that validates each destination before following it. 7. Consider an explicit public-domain allowlist or a controlled outbound proxy. 8. Apply response-size limits in addition to the existing timeout. 9. Clearly notify users that fetched article content will be submitted to OpenAI when AI processing is enabled. 10. Add tests covering loopback addresses, private ranges, IPv6, alternative numeric IP representations, DNS rebinding scenarios, and redirects to blocked destinations.
