T09 · Insecure Skill Coding Practices
- Location
scripts/media_gen_client.py:79- Finding
Unvalidated Server-Provided URL Enables Arbitrary Resource Retrieval
- Content
View full analysis
Vulnerability Details
File Location:
scripts/media_gen_client.py:79-101, with the untrusted download URL consumed atscripts/media_gen_client.py:265-270
Vulnerability Type: Unrestricted URL fetch / client-side SSRF
Risk Level: MediumVulnerable Code
python def _download_to_file(url: str, out_path: str, timeout_s: int = 300) -> Dict[str, Any]: """ Download a (possibly signed) URL to local file. Designed for OSS signed URLs returned by video generation tasks. """ os.makedirs(os.path.dirname(out_path) or ".", exist_ok=True) req = urllib.request.Request(url, headers={"User-Agent": "OpenClaw-Media-Gen/1.0"}) try: with urllib.request.urlopen(req, timeout=timeout_s) as resp, open(out_path, "wb") as f: total = 0 while True: chunk = resp.read(1024 * 1024) # 1MB if not chunk: break f.write(chunk) total += len(chunk) return {"success": True, "saved_to": out_path, "bytes": total} except Exception as e: return {"success": False, "error": str(e), "url": url, "saved_to": out_path}python if status == "SUCCEEDED" and getattr(args, "download", False): video_url = (resp.get("output") or {}).get("video_url") or (resp.get("output") or {}).get("videoUrl") if video_url: out_path = args.out or _safe_filename("mp4") dl = _download_to_file(video_url, out_path) resp = {**resp, "download": dl}Technical Analysis
The video download URL originates in the remote API response and is passed directly to
urllib.request.urlopen. The implementation does not validate the URL scheme, hostname, resolved IP address, port, or redirect chain.Cross-domain downloads may be necessary because media-generation services commonly return signed object-storage URLs. However, unrestricted URL retriev ...[truncated 1850 chars]
- Remediation
View remediation
Remediation Suggestions
- Permit only
httpsdownload URLs. - Reject URLs containing embedded credentials.
- Resolve the hostname before connecting and reject loopback, private, link-local, multicast, unspecified, and reserved IP ranges for both IPv4 and IPv6.
- Validate every redirect target rather than validating only the initial URL.
- Prefer an allowlist of documented AIsa object-storage domains where operationally possible.
- Restrict destination ports to expected HTTPS ports.
- Apply a maximum response size and validate the response content type before writing it as a video.
- Consider requiring explicit user confirmation when the returned download host is outside a trusted allowlist.
- Permit only
