T09 · Insecure Skill Coding Practices
- Location
scripts/research_sources.py:46- Finding
Unrestricted URL Fetching Enables Server-Side Request Forgery
- Content
View full analysis
Optional[str]: """Fetch a URL and return text content. Returns None on failure.""" try: req = urllib.request.Request( url, headers={"User-Agent": "Mozilla/5.0 (compatible; ResearchBot/1.0)"}, ) with urllib.request.urlopen(req, timeout=timeout) as resp: content_type = resp.headers.get("Content-Type", "") if "text" not in content_type and "json" not in content_type: return None return resp.read(max_chars).decode(errors="replace") except Exception: return None ``` Direct document URLs are passed to this helper without destination validation: ```python def search(self, query: str, limit: int = 5) -> list[dict]: """Fetch documentation from a URL or search for relevant docs. If query looks like a URL, fetch it directly. Otherwise, try to discover relevant documentation pages. """ # If query is a URL, fetch directly if query.startswith("http://") or query.startswith("https://"): return self._fetch_doc_page(query) ``` The context expander independently implements the same unsafe behavior: ```python def _fetch_url(url: str, max_chars: int = 30000) -> Optional[str]: """Fetch a URL and return text content.""" try: req = urllib.request.Request( url, headers={"User-Agent": "Mozilla/5.0 (compatible; ResearchBot/1.0)"}, ) with urllib.request.urlopen(req, timeout=15) as resp: content_type = resp.headers.get("Content-Type", "") if "t ...[truncated 2714 chars]- Remediation
View remediation
