T09 · Insecure Skill Coding Practices
- Location
scripts/fetch_feeds.py:95- Finding
Unrestricted Feed URLs Enable Server-Side Request Forgery and Local Resource Access
- Content
View full analysis
bytes | None: """Fetch a URL and return raw bytes, or None on error.""" req = Request(url, headers={"User-Agent": "rss-digest/1.0 (OpenClaw agent)"}) try: with urlopen(req, timeout=timeout) as resp: return resp.read() ``` From `scripts/fetch_feeds.py:251-259`: ```python for i, feed_meta in enumerate(feeds, 1): url = feed_meta.get("xmlUrl", "").strip() if not url: continue title = feed_meta.get("title", url) print(f" [{i}/{len(feeds)}] {title} ...", file=sys.stderr) raw = fetch_url(url, args.timeout) ``` ### Technical Analysis Feed URLs are accepted directly from an OPML document or JSON feed list and passed to Python's `urlopen` without validating their scheme, hostname, resolved address, port, or redirect destination. The legitimate function only requires retrieval of public RSS and Atom resources over HTTP or HTTPS. Allowing arbitrary URL schemes and arbitrary network destinations exceeds that requirement. Depending on the runtime handlers available to `urlopen`, an attacker may supply URLs targeting: - Loopback services such as `127.0.0.1` or `::1`. ...[truncated 2242 chars]- Remediation
View remediation
