T09 · Insecure Skill Coding Practices
- Location
scripts/run_render.py:165- Finding
Unrestricted Retrieval of API-Supplied Media URLs Enables SSRF
- Content
View full analysis
Vulnerability Details
File Location:
scripts/run_render.py:165-169; related URL propagation occurs inclients/avatar_client.py:706-712andclients/ai_creation_client.py:184-190
Vulnerability Type: Server-Side Request Forgery through unvalidated media URLs
Risk Level: MediumVulnerable Code
python def download_url(url: str, dest: Path) -> None: with DOWNLOAD_SEM: req = urllib.request.Request(url, method="GET") with urllib.request.urlopen(req, timeout=300) as resp: dest.write_bytes(resp.read())The downloaded URL is obtained directly from API task results:
python def poll_video_task_url(video_id: str, interval: int = 10, timeout: int = 1800) -> str: data = poll_video_task(video_id, interval=interval, timeout=timeout) video_url = data.get("video_url") if not video_url: raise RuntimeError("Task succeeded but returned no video_url") return str(video_url)python def poll_ai_creation_task_url( unique_id: str, *, interval: int = 10, timeout: int = 1800, ) -> str: data = poll_ai_creation_task(unique_id, interval=interval, timeout=timeout) url = first_output_url(data) if not url: raise RuntimeError("Task succeeded but returned no output_url") return urlTechnical Analysis
The renderer passes URLs from remote API responses directly to
urllib.request.urlopen()without validating:- The URL scheme
- The destination hostname and port
- The resolved IP address
- Redirect destinations
- Whether the destination is an approved Chanjing media host or CDN
- Whether the response is an expected media type
Although these URLs normally originate from the declared Chanjing API, the client treats the API response as fully trusted. A compromised API account, upstream service, DNS path, or maliciously altered task response could make the Agent issue req ...[truncated 1567 chars]
- Remediation
View remediation
Remediation Suggestions
- Accept only
httpsURLs for generated-media downloads. - Maintain an explicit allowlist of approved Chanjing media and CDN hostnames.
- Resolve the hostname before connecting and reject loopback, private, link-local, multicast, unspecified, and reserved addresses.
- Disable automatic redirects or validate the scheme, hostname, port, and resolved address again after every redirect.
- Reject URLs containing embedded credentials or unexpected ports.
- Validate the response
Content-Typeagainst an allowlist of expected audio and video types. - Centralize all media retrieval in one hardened downloader so
download_url(),download_video(), anddownload_ai_creation_result()enforce identical controls. - Run media parsing in a sandbox with restricted network access, filesystem access, CPU, and memory.
- Accept only
