T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/tts.py:98
- Finding
- Unvalidated Server-Provided Download URL Enables SSRF and Unbounded Downloads<![CDATA[ ## Vulnerability Details **File Location**: `scripts/tts.py`, lines 98-111 **Vulnerability Type**: Unvalidated remote URL, unrestricted redirects, and unbounded response buffering **Risk Level**: Medium ### Vulnerable Code ```python def download_file(file_id: str, output_path: str): """下载音频文件""" url = f"{API_HOST}/v1/files/retrieve" params = {"file_id": file_id} resp = requests.get(url, headers=HEADERS, params=params, timeout=30) resp.raise_for_status() download_url = resp.json()["file"]["download_url"] with open(output_path, "wb") as f: vr = requests.get(download_url, timeout=60) vr.raise_for_status() f.write(vr.content) print(f"✅ 文件已下载: {output_path}") ``` ### Technical Analysis The script trusts the `download_url` returned by the MiniMax API and passes it directly to `requests.get`. It does not validate: - The URL scheme - The destination hostname - The resolved IP address - Redirect destinations - Whether the target is a loopback, private, link-local, or reserved address - The response size or declared content type The `requests` library follows HTTP redirects by default. Consequently, even an initially trusted URL can redirect the client to a sensitive internal destination. Exploitation requires control over, or compromise of, the API response or an upstream service capable of influencing the returned download URL. The response is also read through `vr.content`, which buffers the complete body in memory before writing it. No maximum response size is enforced, creating memory and disk exhaustion risk. The API authorization header is not forwarded to the download URL, which limits direct exposure of `MINIMAX_API_KEY`. ### Attack Path 1. An attacker compromises or gains influence over the API response associated with a TTS file retrieval request. 2. The response supplies a malicious `download_url`, or a URL that redirects to an attacker-selected destination. 3. The skill automatically ...[truncated 1169 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Accept only HTTPS download URLs. 2. Maintain an explicit allowlist of approved MiniMax and trusted CDN hostnames. 3. Resolve the hostname before connecting and reject loopback, private, link-local, multicast, unspecified, and reserved IP ranges. 4. Disable automatic redirects with `allow_redirects=False`, or validate every redirect target using the same scheme, hostname, and IP checks. 5. Stream downloads with `stream=True` instead of buffering the entire response through `vr.content`. 6. Enforce a strict maximum download size using both `Content-Length` and a running byte counter while streaming. 7. Validate the response content type against expected audio types. 8. Download to a temporary file in the destination directory and atomically replace the final output only after all validation succeeds. 9. Apply separate connection and read timeouts and remove partial files when an error occurs. Example hardened pattern: ```python with requests.get( validated_url, stream=True, timeout=(10, 60), allow_redirects=False, ) as response: response.raise_for_status() total = 0 with open(temp_path, "wb") as output: for chunk in response.iter_content(chunk_size=64 * 1024): if not chunk: continue total += len(chunk) if total > MAX_AUDIO_BYTES: raise ValueError("Audio download exceeds the permitted size") output.write(chunk) ``` ]]>
