T09 · Insecure Skill Coding Practices
- Location
scripts/prepare_papers.py:94- Finding
Unrestricted URL Fetching Enables Server-Side Request Forgery
- Content
View full analysis
Path: dest_dir.mkdir(parents=True, exist_ok=True) last_error: Exception | None = None for attempt in range(max_retries + 1): try: req = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0 paper-analysis-evidence"}) with urllib.request.urlopen(req, timeout=timeout) as resp: content_type = resp.headers.get("Content-Type") name = guess_download_name(url, content_type) dest = dest_dir / name if dest.exists(): stem, suffix = dest.stem, dest.suffix digest = hashlib.sha1(url.encode("utf-8")).hexdigest()[:8] dest = dest_dir / f"{stem}_{digest}{suffix}" with open(dest, "wb") as f: shutil.copyfileobj(resp, f) return dest ``` ### Technical Analysis The `url` value originates from the user-controlled `--urls` argument and is passed directly to `urllib.request.urlopen()`. The implementation does not: - Restrict URLs to approved HTTP or HTTPS schemes. - Reject loopback, private, link-local, multicast, or reserved IP addresses. - Resolve hostnames and validate all resulting addresses. - Validate redirect destinations. - Restrict requests to known paper repositories. - Prevent access to cloud instance metadata endpoints or internal services. Because the request originates from the machine running the Skill, an attacker can use the downloader as a network proxy into resources that may not be reachable from the attacker directly. ### Attack Path 1. An attacker supplies a URL that resolves to an internal service, loopback address, or cloud metadata endpoint. ...[truncated 1051 chars]- Remediation
View remediation
