T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/generate.py:160
- Finding
- Unrestricted URL Fetching Enables Server-Side Request Forgery<![CDATA[ ## Vulnerability Details **File Location**: `scripts/generate.py:160-176, 193-239` **Vulnerability Type**: Server-Side Request Forgery (SSRF) through user-controlled URLs and redirects **Risk Level**: High ### Vulnerable Code ```python def download_to_file(client: httpx.Client, url: str, dest: Path) -> bool: """Download a URL to a local file. Returns True on success.""" try: headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36", "Accept": "image/*,*/*;q=0.8", } response = client.get(url, headers=headers, follow_redirects=True, timeout=20.0) if response.status_code == 200 and len(response.content) > 1000: content_type = response.headers.get("content-type", "") if "image" in content_type or "octet" in content_type or len(response.content) > 5000: dest.parent.mkdir(parents=True, exist_ok=True) dest.write_bytes(response.content) size_kb = len(response.content) / 1024 print(f" ✓ Downloaded: {dest.name} ({size_kb:.0f}KB)", flush=True) return True except Exception as e: print(f" ✗ Download failed: {e}", flush=True) return False ``` ```python def fetch_product_image(client: httpx.Client, product_url: str, dest: Path) -> bool: """Try to find and download the main product image from a product page.""" try: from bs4 import BeautifulSoup except ImportError: print(" ⚠ beautifulsoup4 not available for product image extraction", flush=True) return False print(" Fetching product page for main image...", flush=True) try: headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36", "Accept": "text/html,*/*", } response = client.get(product_url, headers=headers, follow_redirects=True, timeout=20.0) if response.status_cod ...[truncated 4559 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Permit only explicitly required URL schemes, preferably `https`. 2. Parse and validate every user-provided, extracted, and redirected URL before requesting it. 3. Resolve destination hostnames and reject: - IPv4 and IPv6 loopback addresses - Private address ranges - Link-local addresses - Multicast, reserved, and unspecified addresses - Cloud metadata destinations 4. Repeat validation after every redirect and DNS resolution to prevent redirect-based and DNS-rebinding bypasses. 5. Reject URLs containing embedded credentials. 6. Restrict nonstandard destination ports unless explicitly needed. 7. Consider an allowlist of supported commerce domains or require interactive approval before contacting a new domain. 8. Replace automatic redirect handling with a bounded manual redirect loop that validates each target. 9. Decode downloaded data with a trusted image library and reject content that is not a valid supported image. Do not treat response size as proof that content is an image. 10. Enforce strict response-size limits to prevent excessive memory or disk consumption. 11. Run the fetcher in a network-isolated environment with no access to local, private, or metadata networks. 12. Keep auto-fetch disabled in untrusted workflows and prefer user-provided product images. ]]>
