T09 · Insecure Skill Coding Practices
Error
- Location
- assets/downloader.py:261
- Finding
- API Key Disclosure to API-Controlled Download Hosts## Vulnerability Details **File Location**: `assets/downloader.py:105-126`, `assets/downloader.py:261-270`, and `assets/downloader.py:310-345` **Vulnerability Type**: Credential disclosure across trust boundaries **Risk Level**: High ### Vulnerable Code ```python def download_file(session, url, filepath, desc="Downloading"): """Download a file with progress display.""" try: resp = session.get(url, stream=True, timeout=120) resp.raise_for_status() total = int(resp.headers.get("content-length", 0)) downloaded = 0 with open(filepath, "wb") as f: for chunk in resp.iter_content(chunk_size=8192): if chunk: f.write(chunk) downloaded += len(chunk) if total > 0: pct = int(downloaded * 100 / total) bar = "█" * (pct // 5) + "░" * (20 - pct // 5) print(f"\r {bar} {pct}%", end="", flush=True) print() return True except requests.exceptions.RequestException as e: error(f"Download failed: {e}") return False ``` ```python session = requests.Session() session.headers.update({ "Content-Type": "application/json", "X-API-KEY": api_key, }) try: resp = session.post(API_URL, json={"url": url, "source": "短视频下载器-ClawHub"}, timeout=30) result = resp.json() ``` ```python if aweme_type == "video": video_url = data.get("videoUrl") if not video_url: error("API did not return video URL") sys.exit(1) safe_title = sanitize_filename(title) or f"video_{platform}" filename = f"{safe_title}.mp4" filepath = os.path.join(output_dir, filename) info(f"Type: Video") step("Downloading video...") if download_file(session, video_url, filepath): downloaded_files.append(filepath) elif aweme_type == "photo": image_urls = data.get("imageUrls") or [] if not image_urls: err ...[truncated 2478 chars]
- Remediation
- ## Remediation Suggestions - Do not store authentication headers in a session reused for untrusted downloads. - Attach the API key only to the parsing request: ```python api_session = requests.Session() resp = api_session.post( API_URL, headers={ "Content-Type": "application/json", "X-API-KEY": api_key, }, json={"url": url, "source": "video-downloader"}, timeout=30, ) ``` - Use a separate unauthenticated session for media downloads: ```python download_session = requests.Session() download_file(download_session, video_url, filepath) ``` - Parse every returned media URL with `urllib.parse.urlsplit`. - Require HTTPS and reject embedded credentials, malformed hostnames, and unexpected schemes. - Where the service contract permits it, enforce an explicit allowlist of trusted media or CDN hosts. - Ensure authentication headers are not forwarded through redirects to a different origin. - Rotate potentially exposed user keys after deploying the fix.
