T09 · Insecure Skill Coding Practices
- Location
- scripts/fetch_news.mjs:49
- Finding
- Unrestricted URL Fetching Enables Server-Side Request Forgery<![CDATA[ ## Vulnerability Details **File Location**: `scripts/fetch_news.mjs:14-16, 49-54, 85-96` **Vulnerability Type**: Server-Side Request Forgery (SSRF) through an unvalidated user-controlled URL **Risk Level**: High ### Complete Vulnerable Code ```js const args = process.argv.slice(2); const url = args.find(a => !a.startsWith('--')); const useDirect = args.includes('--direct'); ``` ```js async function fetchDirect(targetUrl) { const response = await fetch(targetUrl, { headers: { 'User-Agent': 'Mozilla/5.0 (compatible; NewsFetcher/2.0)' } }); if (!response.ok) { throw new Error(`HTTP ${response.status}`); } const text = await response.text(); return { raw_content: text }; } ``` ```js console.log(`🔗 访问链接: ${url}\n`); try { const result = await fetchDirect(url); if (result.raw_content && result.raw_content.length > 300) { console.log(`✅ 成功获取`); console.log(` 📊 ${result.raw_content.length} 字符\n`); console.log('─'.repeat(50)); console.log('📄 内容:\n'); console.log(result.raw_content.substring(0, 5000)); } else { console.log('❌ 内容不足'); } ``` ### Technical Analysis The script accepts a URL directly from command-line input and passes it to `node-fetch` without validating its scheme, hostname, resolved IP address, port, or redirect destinations. Although the declared function only requires access to public news sources, the implementation permits requests to arbitrary network locations reachable from the host. Consequently, an attacker may supply URLs targeting loopback interfaces, private network ranges, link-local addresses, internal DNS names, or cloud instance metadata services. Redirects also require validation because `node-fetch` follows redirects by default; an apparently public URL could redirect to a prohibited internal endpoint. The script reads the response body and prints up to 5,000 characters. This turns otherwise blind SSRF into a response-disclosure channel and may expo ...[truncated 1572 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Restrict accepted schemes to `https:` and permit `http:` only where explicitly required. 2. Prefer an allowlist of approved public news domains. Compare normalized hostnames exactly and prevent deceptive suffix matches. 3. Resolve destination hostnames before connecting and reject: - Loopback addresses. - RFC 1918 private addresses. - Link-local addresses. - Carrier-grade NAT ranges. - Multicast, unspecified, and reserved ranges. - IPv6 loopback, unique-local, link-local, and IPv4-mapped private addresses. 4. Disable automatic redirects or validate the scheme, hostname, and resolved address of every redirect target before following it. 5. Protect against DNS rebinding by ensuring the validated address is the address used for the connection. 6. Apply strict connection and response timeouts. 7. Stream responses with a maximum byte limit instead of loading an unlimited response into memory. 8. Validate response content types and reject unexpected binary or executable content. 9. Avoid printing raw response bodies by default. Extract and return only the news fields required by the Skill. 10. Run the fetcher in a sandbox with outbound network policy that blocks localhost, private networks, and metadata endpoints. ]]>
