T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/generate.py:132
- Finding
- Unvalidated Remote Image URL Enables SSRF and Resource Exhaustion<![CDATA[ ## Vulnerability Details **File Location**: `scripts/generate.py`, lines 132–139 **Vulnerability Type**: Server-Side Request Forgery (SSRF), unrestricted download, and unbounded resource consumption **Risk Level**: Medium ### Vulnerable Code ```python def download_image(url, save_path): """下载图片""" try: response = requests.get(url, timeout=60) if response.status_code == 200: with open(save_path, "wb") as f: f.write(response.content) return True ``` ### Technical Analysis The image URL returned in `result["data"][0]["url"]` by the remote generation API is passed directly to `requests.get()` without validating its scheme, hostname, resolved IP address, redirect destination, content type, or response size. The `requests` library follows HTTP redirects by default. Consequently, even an initially acceptable URL could redirect the client to a loopback, link-local, private, or otherwise restricted network address. The response is also fully buffered through `response.content` and written to disk without a size limit. No image signature or MIME-type verification is performed, and every successful response is stored using a `.jpeg` filename regardless of its actual content. Exploitation requires control over, or compromise of, the generation API response or an image-host redirect target. The downloaded request does not include the Volcengine authorization header, limiting direct credential exposure. ### Attack Path 1. An attacker compromises or influences the image-generation API response, causing its `url` field to contain an attacker-selected URL. 2. Alternatively, the returned image URL points to an endpoint that later redirects to an attacker-selected destination. 3. The script passes that URL directly to `requests.get()`, which follows redirects by default. 4. The process requests a local, private-network, link-local, cloud-metadata, or arbitrary Internet endpoint using the network priv ...[truncated 1110 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Permit only HTTPS image URLs. 2. Maintain an explicit allowlist of trusted image-delivery hostnames. 3. Resolve the hostname before connecting and reject loopback, private, link-local, multicast, reserved, and unspecified IP ranges for both IPv4 and IPv6. 4. Disable automatic redirects with `allow_redirects=False`, or validate the scheme, hostname, and resolved address at every redirect hop. 5. Download with `stream=True` and enforce a strict maximum response size using both `Content-Length` and the actual number of streamed bytes. 6. Require an expected image MIME type, such as `image/jpeg` or `image/png`. 7. Validate the downloaded file's signature and decode it with a trusted image parser before accepting it. 8. Write to a temporary file first and atomically move it to the final path only after all validations succeed. 9. Delete partial files when validation or downloading fails. 10. Apply outbound network restrictions at the operating-system or container level so the Skill cannot reach internal services or cloud metadata endpoints. ]]>
