T09 · Insecure Skill Coding Practices
- Location
scripts/generate_brief.py:18- Finding
Unrestricted URL Fetching Enables Server-Side Request Forgery and Local Resource Access
- Content
View full analysis
str: req = urllib.request.Request(url, headers={"User-Agent": "openclaw-hn-rss-brief/1.0"}) with urllib.request.urlopen(req, timeout=timeout) as r: charset = r.headers.get_content_charset() or "utf-8" return r.read().decode(charset, errors="replace") ``` The initial OPML source is retrieved without destination validation: ```python if args.opml_url: opml_text = fetch_text(args.opml_url, timeout=args.timeout) else: with open(args.opml_file, 'r', encoding='utf-8') as f: opml_text = f.read() feed_urls = parse_opml(opml_text)[: args.max_feeds] ``` Every URL extracted from the OPML document is subsequently fetched: ```python def work(url: str) -> Tuple[str, List[Entry], Optional[str]]: try: text = fetch_text(url, timeout=args.timeout) es = parse_feed(url, text) return url, es, None except Exception as e: return url, [], str(e) ``` ### Technical Analysis The Skill legitimately requires outbound network access to retrieve an OPML subscription list and its RSS or Atom feeds. However, the implementation grants substantially broader network access than this functionality requires. Both the user-supplied `--opml-url` and every `xmlUrl` extracted from an OPML document are passed directly to `urllib.request.urlopen`. The implementation does not: - Restrict requests to HTTP or HTTPS. - Require encrypted HTTPS transport. - Reject URLs containing embedded credentials. - Block loopback, private, link-local, multicast, reserved, or cloud metadata IP addresses. - Revalidate hostnames after DNS resolution. - Validate redirect destinations. - Restrict feed retrieval to trusted domains. - Exp ...[truncated 2336 chars]- Remediation
View remediation
