T09 · Insecure Skill Coding Practices
- Location
clawcat/adapters/news/rss.py:24- Finding
Planner-Controlled RSS URLs Permit Server-Side Request Forgery
- Content
View full analysis
FetchResult: import asyncio config = config or {} feeds = config.get("feeds", DEFAULT_FEEDS) max_per_feed = config.get("max_per_feed", 10) items: list[Item] = [] seen_urls: set[str] = set() for feed_cfg in feeds: url = feed_cfg.get("url", "") label = feed_cfg.get("label", url[:40]) if not url: continue try: parsed = await asyncio.to_thread(feedparser.parse, url) ``` ### Technical Analysis `SourceSelection.config` is an unrestricted dictionary generated by the planner LLM. The fetch node merges this dictionary into the adapter configuration without schema validation. The RSS adapter then passes each supplied URL directly to `feedparser.parse()`. There is no validation of: - The URL scheme - The destination hostname - Resolved IP addresses - Loopback, link-local, private, or reserved address ranges - Cloud instance metadata endpoints - Redirect destinations Although custom RSS ...[truncated 1491 chars]- Remediation
View remediation
