T09 · Insecure Skill Coding Practices
Error
- Location
- kb-builder.js:108
- Finding
- Unrestricted URL Fetching Enables Server-Side Request Forgery<![CDATA[ ## Vulnerability Details **File Location**: `kb-builder.js:108-127` **Vulnerability Type**: Server-Side Request Forgery (SSRF) **Risk Level**: High ### Vulnerable Code ```javascript // Scrape FAQ from URL async function scrapeFromURL(url) { return new Promise((resolve, reject) => { const client = url.startsWith('https') ? https : http; client.get(url, (res) => { let data = ''; res.on('data', chunk => data += chunk); res.on('end', () => { // Simple HTML text extraction const text = data .replace(/<script[^>]*>[\s\S]*?<\/script>/gi, '') .replace(/<style[^>]*>[\s\S]*?<\/style>/gi, '') .replace(/<[^>]+>/g, ' ') .replace(/ /g, ' ') .replace(/\s+/g, ' ') .trim(); resolve(text); }); }).on('error', reject); }); } ``` The user-controlled URL reaches this function through the `scrape` command: ```javascript const url = getArg('--url'); const outputPath = getArg('--output') || './kb.json'; if (!url) { console.error('Error: --url is required'); process.exit(1); } console.log(`Scraping FAQ from ${url}...`); const text = await scrapeFromURL(url); const entries = parseFAQ(text); ``` ### Technical Analysis The application performs an outbound HTTP or HTTPS request to a URL supplied through the `--url` argument. It does not validate the destination hostname, port, or resolved IP address and does not reject loopback, private, link-local, or other reserved address ranges. Consequently, the process can be instructed to connect to resources that are inaccessible to the external attacker but accessible from the host running the Skill. Potential targets include: - Services bound to `127.0.0.1` or `::1` - Services on private network ranges - Container or orchestration control endpoints - Link-local cloud metadata services - Unauthenticated internal administration interfaces The response is converted to text, parsed as FAQ conte ...[truncated 1375 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Parse input with `new URL()` and explicitly permit only `http:` and `https:`. 2. Adopt an allowlist of approved domains whenever the expected destinations are known. 3. Resolve the hostname before connecting and reject every address in loopback, private, link-local, multicast, documentation, carrier-grade NAT, and other reserved ranges for both IPv4 and IPv6. 4. Prevent DNS rebinding by connecting only to the validated resolved address while preserving the expected hostname for TLS verification. 5. If redirect support is added, repeat the complete validation process for every redirect destination and limit the number of redirects. 6. Reject nonstandard ports unless they are explicitly required. 7. Place outbound network restrictions around the process so that it cannot reach metadata endpoints, management networks, or internal services. 8. Avoid returning or persisting response bodies from destinations that have not passed validation. ]]>
