T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/feishu_image.py:109
- Finding
- Arbitrary Image URL Fetching Enables Server-Side Request Forgery and Data Disclosure<![CDATA[ ## Vulnerability Details **File Location**: `scripts/feishu_image.py`, lines 109-120 and 186-208 **Vulnerability Type**: Server-Side Request Forgery (SSRF) with external data upload **Risk Level**: High ### Vulnerable Code ```python def download_image(url, dest): """Download an image URL to a local file. Returns True on success.""" try: req = urllib.request.Request(url, headers={ "User-Agent": "Mozilla/5.0 (compatible; FeishuImageBot/1.0)", }) with urllib.request.urlopen(req, timeout=15, context=_ssl_ctx) as resp: with open(dest, "wb") as f: f.write(resp.read()) return True except Exception as e: print(f"[feishu_image] download failed {url}: {e}", file=sys.stderr) return False ``` The downloaded content is subsequently uploaded to Feishu: ```python for i, m in enumerate(matches): url = m.group(2) if url in url_to_key: continue if url.startswith("img_"): url_to_key[url] = url continue ext = os.path.splitext(urllib.parse.urlparse(url).path)[1] or ".jpg" dest = os.path.join(tmpdir, f"img_{i}{ext}") if download_image(url, dest): try: image_key = upload_image_to_feishu(dest, token) url_to_key[url] = image_key print(f"[feishu_image] uploaded {url[:80]}... -> {image_key}", file=sys.stderr) except Exception as e: print(f"[feishu_image] upload failed: {e}", file=sys.stderr) ``` ### Technical Analysis Markdown image URLs are extracted from model-generated search output and passed directly to `urllib.request.urlopen`. The implementation does not validate: - The URL scheme. - The destination hostname or resolved IP address. - Whether the address belongs to a loopback, private, link-local, reserved, or cloud metadata range. - Redirect targets. - The response MIME type. - The response size. - Whether the response is actually an image. Consequently, ...[truncated 1780 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Permit only HTTPS image URLs. 2. Resolve the hostname before connecting and reject all loopback, private, link-local, multicast, unspecified, reserved, and metadata-service addresses for both IPv4 and IPv6. 3. Disable automatic redirects or validate the hostname and resolved addresses of every redirect target. 4. Prevent DNS rebinding by ensuring that validation and connection use the same resolved address. 5. Require an approved image MIME type and verify the file signature rather than trusting the extension or `Content-Type` header alone. 6. Enforce strict response-size, timeout, and image-dimension limits while streaming the response. 7. Consider an allowlist of trusted image-hosting domains returned by the search provider. 8. Do not upload a downloaded resource until image decoding and validation succeed. ]]>
