T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/rss_monitor.py:68
- Finding
- Unrestricted RSS Feed Retrieval Enables Server-Side Request Forgery<![CDATA[ ## Vulnerability Details **File Location**: `scripts/rss_monitor.py:68-91` **Vulnerability Type**: Server-Side Request Forgery through unvalidated feed URLs **Risk Level**: Medium ### Complete Code Snippet ```python def fetch_feeds(): """Fetch all RSS feeds and return new items""" history = load_posted_history() new_items = [] for feed_url in RSS_FEED_URLS: feed_url = feed_url.strip() if not feed_url: continue try: feed = feedparser.parse(feed_url) print(f"✓ Fetched: {feed.feed.get('title', feed_url)[:50]}") for entry in feed.entries[:10]: # Limit to 10 latest per feed link = entry.get('link', '') if link and not is_already_posted(link, history): new_items.append({ 'title': entry.get('title', 'No title'), 'link': link, 'summary': entry.get('summary', '')[:500], 'published': entry.get('published', ''), 'source': feed.feed.get('title', feed_url) }) except Exception as e: print(f"✗ Error fetching {feed_url}: {e}") ``` ### Technical Analysis The Skill reads feed locations from the `RSS_FEED_URLS` environment variable and passes each value directly to `feedparser.parse()`. It does not validate: - The URL scheme. - The destination hostname. - Resolved IP addresses. - Redirect destinations. - Whether the destination belongs to a loopback, private, link-local, reserved, or cloud metadata network. - Response size or request duration. Consequently, a party capable of controlling the environment variable can instruct the runtime to issue requests using the runtime's network position. The intended functionality only requires access to explicitly approved public RSS endpoints, so unrestricted access to arbitrary network destination ...[truncated 1931 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Accept only `https` feed URLs unless another scheme is explicitly required. 2. Parse and normalize each URL before use, rejecting embedded credentials, malformed hosts, and unexpected ports. 3. Resolve the hostname and reject all loopback, private, link-local, multicast, reserved, and unspecified IPv4 and IPv6 addresses. 4. Explicitly block known cloud metadata destinations, including link-local metadata addresses. 5. Validate every redirect destination using the same policy; do not rely only on validation of the original URL. 6. Prefer an explicit allowlist of approved feed domains where the deployment model permits it. 7. Use an HTTP client with defined connection and read timeouts, a maximum redirect count, and a strict response-size limit. 8. Restrict outbound traffic at the container or host level so the Skill can reach only approved public destinations. 9. Log rejected destinations without exposing credentials or other sensitive URL components. 10. Add tests covering direct private addresses, DNS names resolving to private addresses, IPv6 literals, alternate address representations, and public-to-private redirects. ]]>
