T09 · Insecure Skill Coding Practices
- Location
sources/rss.py:39- Finding
Configurable RSS URLs Permit Server-Side Request Forgery and Local Resource Access
- Content
View full analysis
str: """Fetch URL content""" try: req = urllib.request.Request(url, headers={ "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36" }) with urllib.request.urlopen(req, timeout=timeout) as resp: return resp.read().decode("utf-8", errors="replace") except Exception as e: print(f" WARNING: Failed to fetch {url}: {e}") return "" ``` ### Technical Analysis The URL is obtained from the user-configurable RSS source definition and passed directly to `urllib.request.urlopen()` without validating: - The URL scheme - The resolved destination address - Whether the destination is loopback, private, link-local, or reserved - Redirect destinations - The response content type - The maximum response size A timeout only limits request duration and does not prevent requests to internal resources. Depending on available URL handlers and the runtime environment, non-HTTP schemes may also permit access to local resources. An initially public URL may redirect to an internal destination because redirect targets are not revalidated. The entire response is read into memory without a byte limit, which also exposes the process to memory exhaustion from a malicious or unexpectedly large feed. ### Attack Path 1. An attacker obtains the ability to create or modify the Skill's `config.yaml`, or convinces an operator to add an attacker-controlled RSS feed. 2. The attacker configures a feed URL targeting a local, private, link-local, cloud metadata, or attacker-controlled redirect endpoint. 3. `scripts/discover.py` loads the source and invokes `RSSSource.fetch()`. 4. `_fetch_url()` sends the request from the OpenClaw host without destination restri ...[truncated 917 chars]- Remediation
View remediation
