T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/price_watch.py:121
- Finding
- Server-Side Request Forgery Through Unrestricted Product URLs<![CDATA[ ## Vulnerability Details **File Location**: `scripts/price_watch.py`, lines 121–143; related input and execution flow at lines 206–207 and 275–277 **Vulnerability Type**: Server-Side Request Forgery (SSRF) **Risk Level**: High ### Vulnerable Code ```python def validate_url(url: str) -> None: p = urlparse(url) if p.scheme not in {"http", "https"}: raise ValueError("Only http/https URLs are allowed") if not p.netloc: raise ValueError("Invalid URL") def fetch_html(url: str) -> str: validate_url(url) req = Request(url, headers={"User-Agent": UA}) with urlopen(req, timeout=TIMEOUT) as r: content_type = (r.headers.get("Content-Type") or "").lower() if "text/html" not in content_type and "application/xhtml+xml" not in content_type: raise ValueError(f"Unsupported content type: {content_type}") raw = r.read(MAX_BYTES + 1) if len(raw) > MAX_BYTES: raise ValueError("Response too large") return raw.decode("utf-8", errors="replace") ``` The direct URL is accepted and persisted through this flow: ```python def cmd_add(args: argparse.Namespace) -> int: data = load_store() result = add_watch_item(data, args.url, args.target_price, args.currency) save_store(data) print(json.dumps({"ok": True, "item": result, "store": str(STORE_PATH)})) return 0 ``` Stored URLs are subsequently fetched through this flow: ```python def check_one(item: Dict[str, Any]) -> Dict[str, Any]: checked_at = now_iso() try: title, price, debug = parse_product(item["url"]) except Exception as e: return {"id": item["id"], "ok": False, "error": str(e), "checkedAt": checked_at} ``` ### Technical Analysis The URL validation only confirms that the scheme is `http` or `https` and that a network location exists. It does not reject: - Loopback addresses such as `127.0.0.1` or `::1` - Private network ranges - Link-local addresses - Cloud instance ...[truncated 2561 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Validate URLs both when they are added and immediately before every request. 2. Resolve the destination hostname and reject every address in loopback, private, link-local, multicast, reserved, or unspecified IPv4 and IPv6 ranges. 3. Disable automatic redirect handling or implement a custom redirect handler that validates every redirect target before following it. 4. Impose a strict redirect limit and reject HTTPS-to-HTTP downgrade redirects. 5. Mitigate DNS rebinding by connecting only to a validated resolved address while preserving correct TLS hostname verification and the intended HTTP `Host` value. 6. Consider enforcing an explicit allowlist of approved ecommerce domains for all product fetches. 7. Reject URLs containing unexpected credentials, malformed hostnames, or ambiguous address representations. 8. Apply outbound firewall or proxy rules so the process cannot reach internal networks or metadata services. 9. Minimize response data returned in errors and debugging fields to reduce information disclosure. 10. Add automated tests covering IPv4, IPv6, encoded IP representations, DNS rebinding scenarios, redirect chains, localhost, private ranges, and cloud metadata addresses. ]]>
