T09 · Insecure Skill Coding Practices
- Location
lib/audit.py:55- Finding
Unrestricted URL Fetching Enables Server-Side Request Forgery
- Content
View full analysis
ContentTarget: request = urllib.request.Request(url, headers={"User-Agent": "GeoContentGuard/0.1"}) with urllib.request.urlopen(request, timeout=25) as response: body = response.read(max_chars * 3).decode("utf-8", errors="ignore") final_url = response.geturl() content_type = response.headers.get("content-type", "") ``` The caller passes the command-line URL directly to this function: ```python if args.command == "scan-url": return fetch_url(args.url, max_chars) ``` ### Technical Analysis The `scan-url` command accepts an arbitrary URL and passes it to `urllib.request.urlopen` without validating: - The URL scheme. - The destination hostname. - The resolved IP address. - Whether the address belongs to a loopback, private, link-local, reserved, or multicast range. - Whether the destination is a cloud instance metadata service. - Redirect destinations. This creates an SSRF primitive. An attacker who can control or influence the URL being scanned can make the host running the Skill issue requests to network locations that may not be directly accessible to the attacker. The standard URL handler follows HTTP redirects. Consequently, validating only the original hostname would not be sufficient: a public endpoint could redirect the request to an internal address unless every redirect target is independently resolved and validated. The response body is read and analyzed as content. When optional AI review is also enabled, part of an internally retrieved response can additionally be transmitted to the configured external AI endpoint. ### Attack Path 1. An attacker supplies or influences a URL passed to the `scan-url` command. 2. The attacker chooses ...[truncated 1542 chars]- Remediation
View remediation
