T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/generate_meme.py:151
- Finding
- Unrestricted Download of a Server-Supplied URL Enables SSRF## Vulnerability Details **File Location**: `scripts/generate_meme.py`, lines 151–162 **Vulnerability Type**: Server-Side Request Forgery through an unvalidated image URL **Risk Level**: Medium ### Vulnerable Code ```python def _download_image(url: str) -> bytes: image_resp = requests.get(url, timeout=120) image_resp.raise_for_status() return image_resp.content def _extract_image_bytes(result: dict) -> bytes: data = result.get("data") or [] if not data: raise RuntimeError("图片接口未返回 data") first = data[0] if first.get("url"): return _download_image(first["url"]) ``` ### Technical Analysis The image API response controls `data[0].url`, which is passed directly to `requests.get` without validating: - The URL scheme - The destination hostname - The resolved IP address - Redirect destinations - The response content type - The response body size - Whether the body is a valid image The configured model endpoint can therefore cause the runtime to make arbitrary outbound requests. This risk is amplified because `requests.get` follows redirects by default and `MEME_MODEL_BASE_URL` is configurable. This is an SSRF vulnerability rather than remote payload execution: the downloaded bytes are written to disk, but the audited code does not execute them. ### Attack Path 1. An attacker controls or compromises the configured OpenAI-compatible model endpoint. 2. The victim invokes the Skill to generate an image. 3. The malicious endpoint returns a response whose `data[0].url` points to a loopback, private-network, link-local, or cloud metadata address. 4. `_extract_image_bytes` forwards the URL to `_download_image`. 5. `requests.get` accesses the target and follows any redirects without destination validation. 6. The target response is returned as image content and written to the configured output path. ### Impact Assessment An attacker controlling the ...[truncated 568 chars]
- Remediation
- ## Remediation Suggestions 1. Prefer `b64_json` API responses so the client does not need to retrieve a second server-selected URL. 2. If URL downloads remain necessary, require HTTPS and enforce an explicit allowlist of trusted image-host domains. 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 redirects with `allow_redirects=False`, or validate every redirect target using the same scheme, hostname, and resolved-address rules. 5. Account for DNS rebinding by ensuring that the validated address is the address used for the connection. 6. Stream the response and enforce a strict maximum download size. 7. Accept only expected image media types and verify the file signature and decodability before saving it. 8. Apply outbound network controls that prevent the Skill process from reaching internal services and cloud metadata endpoints. 9. Reject URLs containing embedded credentials or unsupported ports.
