T09 · Insecure Skill Coding Practices
Warning
- Location
- SKILL.md:96
- Finding
- Unrestricted server-side fetching of URLs extracted from untrusted pages## Vulnerability Details **File Location**: `SKILL.md`, lines 96-118 **Vulnerability Type**: Server-Side Request Forgery (SSRF) in generated route code **Risk Level**: Medium ### Vulnerable Code ```typescript const items = $('{list_selector}').map((_, element) => { const $el = $(element); return { title: $el.find('{title_selector}').text().trim(), link: new URL($el.find('{link_selector}').attr('href'), baseUrl).href, pubDate: parseDate($el.find('{date_selector}').text().trim(), 'YYYY-MM-DD'), category: $el.find('{category_selector}').text().trim(), }; }).get(); // 获取全文内容(可选) const fulltextItems = await Promise.all( items.slice(0, 10).map(async (item) => { try { const detailResponse = await got({ method: 'get', url: item.link }); const detail$ = load(detailResponse.data); item.description = detail$('{content_selector}').html(); return item; } catch { return item; } }) ); ``` The same unsafe fetching pattern is also recommended in `references/dev-guide.md`, lines 70-74: ```typescript const items = await pMap(list, async (item) => { if (fulltext) { const { data } = await got(item.link); item.description = load(data)('.content').html(); } ``` ### Technical Analysis The generated route obtains link destinations from HTML controlled by the remote source website. The `URL` constructor accepts absolute URLs, so an absolute `href` overrides the expected `baseUrl` origin. The resulting `item.link` is passed directly to `got` without validating: - The URL protocol. - The destination hostname. - Whether the hostname resolves to a private, loopback, link-local, or reserved address. - Redirect destinations. - Whether the destination remains on the analyzed website's approved origin. - Response size and other resource-consumption limits. ...[truncated 2453 chars]
- Remediation
- ## Remediation Suggestions 1. Allow only `http:` and `https:` URLs. 2. Enforce an explicit hostname allowlist. For ordinary article extraction, require the destination hostname to equal the source hostname or belong to a narrowly defined set of approved origins. 3. Resolve destination hostnames before each request and reject loopback, private, link-local, multicast, unspecified, and reserved IPv4 and IPv6 ranges. 4. Prevent DNS rebinding by connecting only to the validated resolved address while preserving the intended HTTP host and TLS server name. 5. Disable automatic redirects or validate the protocol, hostname, and resolved addresses of every redirect target before following it. 6. Apply strict connection, request, and overall timeouts, response-size limits, and concurrency limits. 7. Make full-text retrieval opt-in rather than automatic. 8. Reject malformed or missing `href` values before invoking the `URL` constructor. 9. Apply the same safeguards to both the primary template in `SKILL.md` and the example in `references/dev-guide.md`. 10. Use outbound firewall or proxy rules as defense in depth to prevent the RSSHub process from accessing metadata services and sensitive internal networks.
