T09 · Insecure Skill Coding Practices
Warning
- Location
- main.py:23
- Finding
- Unrestricted URL Fetching Enables SSRF-Style Internal Network Probing## Vulnerability Details **File Location**: `main.py`, lines 23-28 and 100-104 **Vulnerability Type**: Server-Side Request Forgery (SSRF) / unrestricted outbound requests **Risk Level**: Medium ### Vulnerable Code ```python headers = {'User-Agent': 'website-monitor/1.0 (ClawHub)'} req = Request(url, headers=headers) start = time.monotonic() try: resp = urlopen(req, timeout=timeout) ``` The attacker-controlled URL reaches this request through: ```python results = [] for url in args.urls: if not url.startswith(('http://', 'https://')): url = 'https://' + url r = check_url(url, args.timeout, args.expect, args.contains, args.hash_check) ``` ### Technical Analysis The application makes network requests to user-supplied URLs without validating the destination hostname, resolved IP address, port, or redirect target. It does not prevent connections to loopback, private, link-local, reserved, or cloud metadata address ranges. Python's `urlopen` also follows supported HTTP redirects by default. Consequently, validating only the initial URL scheme would not be sufficient: a public URL could redirect the request to an internal resource unless every redirect destination is independently validated. Although the response body is not printed directly, the program exposes several response oracles: - HTTP status - Response time - Response length - Truncated SHA-256 content hash - Whether attacker-selected text occurs in the response These values can be used to discover internal services and infer information about resources that are accessible from the host running the skill. ### Attack Path 1. An attacker causes an AI agent or automation workflow to invoke the skill with an attacker-selected URL. 2. The URL directly references an internal endpoint, such as a loopback, private-network, or link-local address, or references a public endpoint that redirects to one. 3. `urlopen` connect ...[truncated 932 chars]
- Remediation
- ## Remediation Suggestions 1. Parse URLs with `urllib.parse.urlsplit` and permit only explicitly supported schemes, preferably HTTPS. 2. Reject embedded credentials, malformed hostnames, unexpected ports, and ambiguous numeric IP representations. 3. Resolve the hostname before connecting and reject every address in loopback, private, link-local, multicast, unspecified, reserved, and other non-public ranges using Python's `ipaddress` module. 4. Protect against DNS rebinding by ensuring that the validated address is the address used for the connection, or by applying equivalent network-layer egress controls. 5. Disable automatic redirects or validate the scheme, hostname, port, and resolved addresses of every redirect target before following it. 6. Restrict outbound ports and apply a destination allowlist when the set of monitored websites is known. 7. Run the skill in a sandbox with network egress rules that block internal and metadata networks. 8. If internal monitoring is a required feature, make it an explicit trusted-mode option rather than the default.
