T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/cricket-live.py:102
- Finding
- Weak Cricbuzz Hostname Validation Permits Server-Side Request Forgery## Vulnerability Details **File Location**: `scripts/cricket-live.py`, lines 102-115 **Vulnerability Type**: Server-Side Request Forgery caused by incomplete hostname and redirect validation **Risk Level**: Medium ```python def validate_url(url): """Ensure the URL is a valid Cricbuzz live score page to prevent SSRF.""" parsed = urllib.parse.urlparse(url) if parsed.scheme not in ('http', 'https'): print(f"Error: URL must use http or https (got {parsed.scheme})", file=sys.stderr) sys.exit(1) if not parsed.hostname or not parsed.hostname.endswith('cricbuzz.com'): print(f"Error: URL must be a cricbuzz.com domain (got {parsed.hostname})", file=sys.stderr) sys.exit(1) return url def fetch_raw(match_url): req = urllib.request.Request(match_url, headers={"User-Agent": "Mozilla/5.0"}) return urllib.request.urlopen(req, timeout=15).read().decode("utf-8", errors="ignore") ``` ### Technical Analysis The hostname check uses `parsed.hostname.endswith('cricbuzz.com')` without requiring a DNS label boundary. Consequently, unrelated attacker-controlled domains such as `evilcricbuzz.com` satisfy the validation rule. The implementation also does not validate the resolved IP address. An accepted hostname could resolve or rebind to a loopback, private, link-local, or otherwise restricted address. In addition, `urllib.request.urlopen()` follows HTTP redirects by default, but redirect destinations are not passed through `validate_url()`. An initially permitted destination could therefore redirect the request to an internal service. Although the function claims to prevent SSRF, these weaknesses allow the application to issue requests beyond the Cricbuzz hosts required for its declared functionality. ### Attack Path 1. An attacker or untrusted caller supplies a URL such as `https://evilcricbuzz.com/live-score`. 2. `urlparse()` extracts `evilcricbuzz.com` as the hostname ...[truncated 1383 chars]
- Remediation
- ## Remediation Suggestions 1. Permit only exact Cricbuzz domains with a DNS label boundary: ```python hostname = (parsed.hostname or "").rstrip(".").lower() if hostname != "cricbuzz.com" and not hostname.endswith(".cricbuzz.com"): raise ValueError("Only Cricbuzz hosts are permitted") ``` 2. Prefer a narrow allowlist of the exact hostnames genuinely required by the Skill rather than permitting every subdomain. 3. Require HTTPS and reject embedded credentials, fragments, unexpected ports, and malformed hostnames. 4. Disable automatic redirects or implement a redirect handler that revalidates every destination before following it. 5. Resolve all destination addresses before connecting and reject loopback, private, link-local, reserved, multicast, and unspecified IP ranges for both IPv4 and IPv6. 6. Protect against DNS rebinding by ensuring the validated address is the address used for the connection, or enforce equivalent egress restrictions outside the application. 7. Apply network-level egress controls so this process can connect only to approved Cricbuzz, Telegram, and text-to-speech endpoints.
