T09 · Insecure Skill Coding Practices
- Location
scripts/ai_image_playwright.py:199- Finding
Unrestricted Authenticated URL Fetching from Page-Controlled Image Sources
- Content
View full analysis
Vulnerability Details
File Location:
scripts/ai_image_playwright.py, lines 199-218
Vulnerability Type: Server-Side Request Forgery-like arbitrary URL fetching
Risk Level: HighVulnerable Code
python if platform == "chatgpt": is_candidate = ( info["width"] >= 300 and info["height"] >= 300 and ( "chatgpt.com/backend-api/estuary/content" in info["src"] or "已生成图片" in info["alt"] or ("absolute" in info["className"] and "z-1" in info["className"]) or ("chatgpt.com" in info["src"] and info["width"] >= 500 and info["height"] >= 500) or (info["src"].startswith("http") and info["width"] >= 500 and info["height"] >= 500) ) ) else: is_candidate = info["width"] >= 400 and info["height"] >= 400 if is_candidate: print(f"[download] ✓ Candidate matched: {info['width']}x{info['height']}, src: {info['src'][:60]}...") candidates.append((img, info))python if platform == "chatgpt" and src.startswith("http"): try: print(f"[download] Trying page.request.get()...") response = await page.request.get(src) if response.ok: dest_path.write_bytes(await response.body()) print(f"[download] ✓ Downloaded via page.request") except Exception as exc: print(f"[download] page.request failed: {exc}")Technical Analysis
The ChatGPT candidate-selection logic accepts any image whose source starts with
httpand whose rendered dimensions meet the threshold. The selected URL is then passed directly topage.request.get()without validating its scheme, hostname, resolved address, port, redirect destination, response content type, or response size.Because Playwright's request context is associated with the active browser context, the request may carry cookies applicable to the destination. More importantly, the requ ...[truncated 1581 chars]
- Remediation
View remediation
Remediation Suggestions
- Parse image URLs with a standard URL parser and allow only
https. - Maintain an exact allowlist of required image hosts rather than accepting every HTTP URL.
- Do not use substring checks for hostname validation; compare normalized hostnames against exact approved names or carefully defined subdomains.
- Resolve destination hostnames and reject loopback, private, link-local, multicast, reserved, and unspecified IP address ranges for both IPv4 and IPv6.
- Disable redirects or validate every redirect destination using the same scheme, hostname, port, and resolved-address rules.
- Use a request context that does not automatically share authentication state unless authenticated downloading is strictly required.
- Validate the response
Content-Typeagainst an explicit image-media allowlist. - Impose strict response-size, timeout, and download-count limits before loading the entire response into memory or writing it to disk.
- Decode and validate the response as an actual image before retaining it.
- Parse image URLs with a standard URL parser and allow only
