T09 · Insecure Skill Coding Practices
Warning
- Location
- seedance-api.py:120
- Finding
- Unbounded and Timeout-Free HTTP Requests Enable Resource Exhaustion<![CDATA[ ## Vulnerability Details **File Location**: `seedance-api.py`, lines 120–148 **Vulnerability Type**: Missing network timeouts and unbounded response buffering **Risk Level**: Medium ### Vulnerable Code ```python response = requests.post(API_URL, headers=headers, json=data) result = response.json() ``` ```python while time.time() - start_time < timeout: query_response = requests.get(f"{QUERY_URL}/{task_id}", headers=headers) query_result = query_response.json() ``` ```python if download and video_url: os.makedirs(output_dir, exist_ok=True) filename = f"{prompt[:20]}_{int(time.time())}.mp4" filename = "".join(c for c in filename if c not in r'<>:"/\|?*') filepath = os.path.join(output_dir, filename) print(f"正在下载视频...") video_response = requests.get(video_url) with open(filepath, "wb") as f: f.write(video_response.content) ``` ### Technical Analysis All three HTTP operations are performed without explicit connection or read timeouts. Consequently, the initial task submission, an individual polling request, or the final video download can wait indefinitely if the remote endpoint accepts a connection but does not complete its response. The application-level polling limit does not fully mitigate this issue. The following condition is evaluated only before each polling request: ```python while time.time() - start_time < timeout: ``` If `requests.get()` blocks during a polling request, execution cannot return to the loop condition to enforce the configured timeout. The video response is also accessed through `video_response.content`, which buffers the complete response body in memory before writing it to disk. No maximum response size, content type, HTTP status, or available disk-space validation is applied. Redirects are followed by default. This combination permits a slow or oversized response to consume execution time, memory, and disk resources. The issue does not provide direct privilege escalatio ...[truncated 1690 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Set explicit connection and read timeouts on every request: ```python REQUEST_TIMEOUT = (10, 60) response = requests.post( API_URL, headers=headers, json=data, timeout=REQUEST_TIMEOUT, ) response.raise_for_status() ``` Apply equivalent timeouts and status checks to polling requests. 2. Enforce the overall polling deadline when calculating individual request timeouts so that one request cannot exceed the remaining task deadline. 3. Stream video downloads rather than buffering the entire body: ```python MAX_VIDEO_BYTES = 500 * 1024 * 1024 with requests.get( video_url, stream=True, timeout=(10, 60), ) as video_response: video_response.raise_for_status() content_type = video_response.headers.get("Content-Type", "") if not content_type.lower().startswith("video/"): raise ValueError("Unexpected video response content type") declared_size = video_response.headers.get("Content-Length") if declared_size and int(declared_size) > MAX_VIDEO_BYTES: raise ValueError("Video exceeds the permitted download size") downloaded = 0 with open(filepath, "xb") as output: for chunk in video_response.iter_content(chunk_size=1024 * 1024): if not chunk: continue downloaded += len(chunk) if downloaded > MAX_VIDEO_BYTES: raise ValueError("Video exceeds the permitted download size") output.write(chunk) ``` 4. Remove partial output files when a timeout, validation failure, or download error occurs. 5. Validate the returned URL before downloading it. Require HTTPS and, where compatible with the service contract, allowlist expected CDN hostnames. Revalidate the destination after redirects or disable redirects and process them explicitly. 6. Check available disk capacity before downloading and enforce per-file and cumulative output quotas. 7. Catch `requests.Timeout`, `requests.ConnectionE ...[truncated 110 chars]
