T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/search_feed_episodes.py:98
- Finding
- Unrestricted RSS Feed Fetch Enables Server-Side Request Forgery## Vulnerability Details **File Location**: `scripts/search_feed_episodes.py:98-100`, with attacker-influenced input accepted at `scripts/search_feed_episodes.py:255-256` **Vulnerability Type**: Server-Side Request Forgery (SSRF) and unbounded network response **Risk Level**: High ### Vulnerable Code ```python def fetch_feed(rss_url: str, timeout_seconds: int = DEFAULT_TIMEOUT_SECONDS) -> Any: request = Request(rss_url, headers={"User-Agent": DEFAULT_UA}) with urlopen(request, timeout=timeout_seconds) as response: data = response.read() return feedparser.parse(data) ``` The destination is supplied directly through a command-line argument: ```python parser.add_argument("--rss-url", required=True) ``` It is then forwarded to the vulnerable function without validation: ```python mode = args.mode rss_url = args.rss_url ... parsed_feed = fetch_feed(rss_url) ``` ### Technical Analysis The `--rss-url` value is passed directly to `urllib.request.urlopen`. The implementation does not validate: - The URL scheme - The destination hostname or port - Whether DNS resolves to a public IP address - Loopback, private, link-local, reserved, or cloud metadata addresses - Redirect destinations - The maximum response size Downloading an RSS feed is necessary for the declared podcast-search functionality. However, unrestricted access to arbitrary network destinations exceeds the minimum network privileges needed to retrieve public podcast feeds. An attacker who can influence the supplied RSS URL can make the process send requests to services reachable from the execution environment. This may include loopback services, private network systems, or infrastructure metadata endpoints. A malicious public server could also redirect the request to such a destination. Although the code does not deliberately transmit stored credentials or local files, internal response data may be parsed into feed fields and included in command output. Parser and network error ...[truncated 1578 chars]
- Remediation
- ## Remediation Suggestions 1. Permit only explicitly required schemes, preferably `https`; allow `http` only when compatibility requirements justify it. 2. Parse the URL before use and reject user information, fragments, malformed hosts, and unexpected ports. 3. Resolve the hostname and reject all loopback, private, link-local, multicast, unspecified, documentation, and reserved IPv4 and IPv6 ranges. 4. Disable automatic redirects or validate every redirect target using the same scheme, hostname, port, and resolved-address policy. 5. Re-resolve and validate the destination at connection time to reduce DNS rebinding and time-of-check/time-of-use risks. 6. Prefer accepting only RSS URLs obtained from the trusted Clawsica result workflow rather than arbitrary command-line destinations. 7. Stream the response in chunks and stop after a conservative maximum feed size. 8. Apply both connection and read timeouts. 9. Avoid returning low-level internal connection details to untrusted users. 10. Add security tests covering loopback addresses, RFC 1918 networks, IPv6 local addresses, link-local metadata endpoints, encoded IP representations, redirects, DNS rebinding, unsupported schemes, unusual ports, and oversized responses.
