T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/_lib.js:89
- Finding
- Server-Side Request Forgery Through Unrestricted RSS Feed URLs<![CDATA[ ## Vulnerability Details **File Location**: `scripts/add.js:11`, `scripts/_lib.js:56-69`, and `scripts/_lib.js:89-103` **Vulnerability Type**: Server-Side Request Forgery (SSRF) **Risk Level**: High ### Vulnerable Code `scripts/add.js:11`: ```js const result = await addSubscription(input.url, input.name); ``` `scripts/_lib.js:56-69`: ```js export async function addSubscription(url, name) { const subs = loadSubs(); if (subs.some(s => s.url === url)) { return { success: false, error: '该订阅源已存在' }; } const newSub = { id: generateId(), url, name: name || url, addedAt: new Date().toISOString(), lastFetchedAt: null }; subs.push(newSub); saveSubs(subs); return { success: true, message: '订阅源已添加', subscription: newSub }; } ``` `scripts/_lib.js:89-103`: ```js export async function fetchSubscriptions(targetId = null, format = 'markdown', notify = false, sendFn = null) { const subs = loadSubs(); const targets = targetId ? subs.filter(s => s.id === targetId) : subs; if (targets.length === 0) { return { success: false, error: '没有找到订阅源' }; } const config = loadConfig(); const parser = new Parser(); const results = []; for (const sub of targets) { try { const feed = await parser.parseURL(sub.url); ``` ### Technical Analysis The subscription URL comes directly from JSON input and is stored without validating its scheme, hostname, resolved address, port, or redirect destination. During a subsequent fetch, `rss-parser` passes that stored value to its HTTP retrieval mechanism. This creates an SSRF primitive because the requester can cause the Skill runtime to initiate connections to arbitrary destinations reachable from its network context. Potential targets include: - Loopback services such as `127.0.0.1` or `::1`. - Private network ranges. - Link-local addresses. - Cloud instance metadata services such as `169.254.169.254`. - Internal administrative applications or APIs unavailable to th ...[truncated 1552 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Parse every submitted URL using the platform URL parser and reject malformed values. 2. Allow only explicitly required schemes, preferably `https:`. Reject local-file and non-HTTP protocols. 3. Resolve the hostname before connecting and reject every address in loopback, private, link-local, multicast, unspecified, and reserved ranges for both IPv4 and IPv6. 4. Re-resolve and revalidate the destination at connection time to reduce DNS rebinding exposure. 5. Disable redirects or validate the scheme, hostname, and resolved address after every redirect. 6. Explicitly block cloud metadata destinations and hostnames. 7. Apply strict connection, read, and total request timeouts. 8. Enforce a maximum response size and XML complexity limits. 9. Use network-level egress controls so the process cannot access metadata services or internal administrative networks. 10. Perform the same validation when loading existing subscriptions, because the JSON data file could contain entries created before validation was introduced. ]]>
