T09 · Insecure Skill Coding Practices
- Location
SKILL.md:115- Finding
Unrestricted URL Fetching Enables SSRF, Local File Access, and Resource Exhaustion
- Content
View full analysis
dict: """从URL抓取并提炼""" try: resp = urlopen(url, timeout=10) html = resp.read().decode("utf-8", errors="ignore") # 简单去标签 text = re.sub(r'<[^>]+>', '', html) text = re.sub(r'\s+', ' ', text).strip() reader = ReadingAssistant() return reader.extract(text, source=url) except Exception as e: return {"error": str(e)} ``` ### Technical Analysis The `extract_url` function passes an unvalidated, caller-controlled URL directly to `urllib.request.urlopen`. Although `urlparse` is imported, it is never used to validate the URL. This creates several related security risks: - **Server-Side Request Forgery (SSRF):** A caller can request loopback, link-local, private-network, or otherwise internal endpoints that are reachable from the process running the Skill. - **Local file access:** `urlopen` supports schemes other than HTTP and HTTPS, including `file://`. A crafted URL can therefore cause the process to read files available under its operating-system privileges. - **Redirect-based filter bypass:** Even if validation were later added only to the initial URL, `urlopen` follows HTTP redirects by default. A public endpoint could redirect the request to an internal destination unless every redirect target is independently validated. - **Unbounded response consumption:** `resp.read()` reads the entire response into memory without enforcing a maximum size. A large or indefinitely generated response can consume excessive memory and degrade or terminate the process. - **Persistence of extracted data:** The fetched text is passed to `ReadingAssistant.extract`, which stores extracted portions and metadata in `reading_lo ...[truncated 1940 chars]- Remediation
View remediation
