T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/monitor.py:47
- Finding
- Unrestricted URL Fetching Enables SSRF and Local Resource Disclosure<![CDATA[ ## Vulnerability Details **File Location**: `scripts/monitor.py:47-55`, with attacker-controlled URLs accepted at `scripts/monitor.py:353-356` and `scripts/monitor.py:404-406` **Vulnerability Type**: Server-Side Request Forgery and local resource access **Risk Level**: High ### Vulnerable Code ```python def fetch_url(url: str, headers: dict = None) -> str: req_headers = {"User-Agent": USER_AGENT} if headers: req_headers.update(headers) req = Request(url, headers=req_headers) try: with urlopen(req, timeout=30) as resp: charset = resp.headers.get_content_charset() or 'utf-8' return resp.read().decode(charset, errors='replace') ``` The URL is supplied without validation: ```python p.add_argument("--url", required=True) ``` Additional URLs are also stored without validation: ```python def cmd_add_url(args): config = load_monitor(args.event) config["urls"].append({"url": args.url, "label": args.label or args.url}) save_monitor(config) print(f"✅ Added URL to '{args.event}'") ``` ### Technical Analysis The monitor passes a user-controlled URL directly to `urllib.request.Request` and `urlopen`. It does not restrict the scheme to HTTP or HTTPS, resolve and validate the destination address, block loopback or private address ranges, or validate redirect destinations. Consequently, a crafted monitor can request resources that are not intended to be exposed through the web-monitoring feature. Depending on the URL handlers and network environment available to the process, targets may include: - Local files through a supported local-file URL scheme. - Services listening on loopback interfaces. - Private or link-local network services. - Cloud instance metadata endpoints. - Internal HTTP applications inaccessible to the external attacker. The fetched response is subsequently printed by `cmd_fetch`, included in JSON output, passed to an LLM agent, or written into reports. This creates ...[truncated 1451 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Permit only explicitly supported `http` and `https` schemes. 2. Reject URLs containing credentials or ambiguous host representations. 3. Resolve the hostname before connecting and reject every address in loopback, private, link-local, multicast, reserved, unspecified, and other non-public ranges for both IPv4 and IPv6. 4. Block known cloud metadata destinations, including link-local metadata addresses and provider-specific metadata hostnames. 5. Disable automatic redirects or validate the scheme, hostname, and resolved address after every redirect. 6. Consider an administrator-controlled domain allowlist for scheduled monitors. 7. Apply strict response-size limits while streaming rather than reading the entire response before truncation. 8. Reject unsupported protocols and local-file handlers before constructing the request. 9. Apply the same validation in `create`, `add-url`, configuration loading, and immediately before each request. Validation only at creation time is insufficient because configuration files can be edited directly. 10. Run the monitor in a sandbox with minimal filesystem access and restricted outbound networking as defense in depth. ]]>
