T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/analyze.py:103
- Finding
- Unrestricted Image URL Fetching Enables Server-Side Request Forgery<![CDATA[ ## Vulnerability Details **File Location**: `scripts/analyze.py:103-106` **Vulnerability Type**: Server-Side Request Forgery and unbounded remote resource loading **Risk Level**: Medium ### Vulnerable Code ```python if args.image_url: req = urllib.request.Request(args.image_url, headers={"User-Agent": "OpenClaw-NexN2/1.0"}) with urllib.request.urlopen(req, timeout=30) as resp: return resp.read() ``` ### Technical Analysis The `--image-url` argument is passed directly to `urllib.request.urlopen` without validating its scheme, destination host, resolved IP address, port, or redirect chain. The implementation does not reject loopback, private, link-local, or reserved network ranges. Although the downloaded data is subsequently checked for image magic bytes, that validation occurs only after the network request and response have completed. It therefore cannot prevent requests from reaching internal services. Internal endpoints returning valid image data could also have their contents processed and transmitted to the configured external vision provider. The response is read in full with `resp.read()` and has no maximum-size restriction. An attacker-controlled endpoint can consequently return an excessively large response and consume substantial process memory. ### Attack Path 1. An attacker or untrusted caller supplies an `--image-url` value targeting a service reachable from the Skill host, such as a loopback address, private-network service, or cloud-local endpoint. 2. The Skill resolves and requests that URL using the host's network access. 3. Redirects may move the request to another internal destination because redirect targets are not revalidated. 4. The entire response is loaded into memory before image validation. 5. If the response contains valid image bytes, its content is Base64-encoded and sent to the configured vision API for OCR and description. 6. The resulting OCR or description is returned to the caller and cached, ...[truncated 945 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Permit only explicitly supported schemes, preferably HTTPS. 2. Resolve the destination hostname before connecting and reject all loopback, private, link-local, multicast, unspecified, and reserved IP ranges for both IPv4 and IPv6. 3. Disable automatic redirects or validate the scheme, hostname, port, and resolved address of every redirect target. 4. Consider an allowlist of trusted image hosts when the deployment permits it. 5. Enforce a strict maximum download size using `Content-Length` where available and incremental bounded reads regardless of that header. 6. Apply separate connection and read timeouts. 7. Restrict destination ports to expected web ports. 8. Run the Skill with network-level egress controls that prevent access to internal services and metadata endpoints. 9. Reject URLs containing embedded credentials and normalize hostnames before validation. 10. Perform content-type and magic-byte validation while streaming, terminating the request as soon as it exceeds limits or fails validation. ]]>
