T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/monitor.py:48
- Finding
- Unrestricted URL Fetching Enables SSRF and Local File Access## Vulnerability Details **File Location**: `scripts/monitor.py`, lines 48-61 **Vulnerability Type**: Server-Side Request Forgery (SSRF) and unrestricted URI scheme access **Risk Level**: High ### Vulnerable Code ```python def fetch_content(url: str, selector: str = None, headers: dict = None) -> str: req_headers = { "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) web-monitor/2.0" } if headers: req_headers.update(headers) req = Request(url, headers=req_headers) try: with urlopen(req, timeout=30) as resp: raw = resp.read().decode("utf-8", errors="replace") except HTTPError as e: raise RuntimeError(f"HTTP {e.code}: {e.reason}") ``` ### Technical Analysis The URL accepted by the `add` command is passed directly to `urllib.request.Request` and `urlopen` without validating its scheme, hostname, resolved IP address, port, or redirect destinations. The implementation does not: - Restrict URLs to the `http` and `https` schemes. - Reject loopback, private, link-local, reserved, multicast, or unspecified IP addresses. - Prevent access to supported local-resource schemes such as `file://`. - Validate DNS resolution results. - Revalidate destinations reached through HTTP redirects. - Restrict access to cloud instance metadata services. - Impose a maximum response size before reading the response into memory. Although outbound network access is necessary for the declared website-monitoring functionality, unrestricted access to local resources and private networks exceeds the minimum privileges needed to monitor public web pages. There is no evidence that the code deliberately transmits credentials, environment variables, snapshots, or local files to a hardcoded third party. The principal risk is that attacker-controlled URLs can cause the process to retrieve sensitive resources, after which their contents may be stored ...[truncated 1782 chars]
- Remediation
- ## Remediation Suggestions 1. **Restrict URI schemes** - Parse URLs with `urllib.parse.urlsplit`. - Permit only explicit `http` and `https` schemes. - Reject URLs containing unsupported schemes, missing hostnames, or embedded credentials. 2. **Validate resolved destinations** - Resolve the hostname before making a request. - Use Python's `ipaddress` module to reject every resolved loopback, private, link-local, multicast, reserved, or unspecified address. - Explicitly block cloud metadata destinations such as `169.254.169.254`. - Apply validation to both IPv4 and IPv6 addresses. 3. **Secure redirect handling** - Disable automatic redirects or implement a custom redirect handler. - Parse, resolve, and validate every redirect destination before following it. - Set a small maximum redirect count. 4. **Reduce DNS rebinding exposure** - Ensure that the address validated is the address used for the connection. - Where feasible, use an outbound proxy or network policy that blocks private and link-local destinations. 5. **Limit resource consumption** - Inspect `Content-Length` when available. - Read responses incrementally and stop after a configured maximum number of bytes. - Apply limits to snapshot and diff retention. 6. **Apply deployment-level controls** - Run the Skill under a dedicated, low-privilege account. - Deny unnecessary filesystem access. - Restrict outbound traffic to approved public destinations where the environment permits it. - Consider an explicit hostname allowlist when monitoring targets can be supplied by untrusted parties. 7. **Add security tests** - Verify rejection of `file://` URLs. - Verify rejection of loopback, RFC1918, link-local, metadata, IPv6-local, and alternate numeric IP representations. - Verify that redirects and DNS changes cannot bypass destination validation.
