T09 · Insecure Skill Coding Practices
Error
- Location
- tools/NewsFetcher.ts:35
- Finding
- Arbitrary News Source URLs Permit Server-Side Request Forgery<![CDATA[ ## Vulnerability Details **File Location**: `tools/Configure.ts:95-110`; `tools/NewsFetcher.ts:35-53` **Vulnerability Type**: Server-Side Request Forgery through unvalidated configurable URLs **Risk Level**: High ### Vulnerable Code `tools/Configure.ts:95-110` accepts a source URL without validating its protocol, hostname, resolved address, or destination: ```ts function parseSource(input: string): NewsSource { const parts = input.split(',').map(p => p.trim()); if (parts.length !== 4) { throw new Error('参数格式错误,示例:"新智元,https://xinzhiyuan.ai/feed,rss,AI"'); } const [name, url, type, category] = parts; if (!name || !url) { throw new Error('新闻源 name 与 url 不能为空'); } if (type !== 'rss' && type !== 'web') { throw new Error('type 只能为 rss 或 web'); } ``` `tools/NewsFetcher.ts:35-53` subsequently requests the configured URL: ```ts private async fetchFromRSS(source: NewsSource): Promise<NewsItem[]> { const feed = await parser.parseURL(source.url); return feed.items.map(item => ({ title: item.title || '', link: item.link || '', pubDate: new Date(item.pubDate || Date.now()), description: item.contentSnippet || item.content, source: source.name, category: source.category, })); } private async fetchFromWeb(source: NewsSource): Promise<NewsItem[]> { const response = await fetch(source.url); const html = await response.text(); ``` ### Technical Analysis The news-source URL is configuration-controlled and reaches network request functions without destination validation. There is no enforcement of HTTPS, no hostname allowlist, no rejection of loopback or private network ranges, no DNS rebinding defense, and no redirect validation. Although `workflows/FetchNews.md` describes a trusted-domain filter, the executable implementation does not apply such a filter. An attacker who can influence the configuration or persuade a user or Agent to add a source can therefore make the pr ...[truncated 1796 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Permit only `https:` URLs unless a documented source specifically requires another secure scheme. 2. Maintain an explicit allowlist of approved news-source hostnames and compare normalized hostnames exactly; do not use substring matching. 3. Resolve the hostname before connecting and reject loopback, link-local, private, multicast, unspecified, and reserved IPv4 and IPv6 addresses. 4. Repeat destination validation after every redirect and restrict the number of redirects. 5. Protect against DNS rebinding by connecting only to the validated resolved address while preserving correct TLS hostname verification. 6. Add strict connection and response timeouts, response-size limits, and content-type checks. 7. Disable arbitrary custom sources by default. If custom sources are necessary, require explicit user confirmation that clearly displays the final hostname. 8. Apply the same validator to both RSS and web source paths. 9. Add tests covering localhost, private IPv4 ranges, IPv6 loopback, encoded IP forms, redirects to private hosts, and DNS rebinding scenarios. ]]>
