T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/weather.py:25
- Finding
- Disabled TLS Verification and Plaintext HTTP Downgrade## Vulnerability Details **File Location**: `scripts/weather.py`, lines 25–42 **Vulnerability Type**: Improper certificate validation and insecure protocol fallback **Risk Level**: Medium ### Vulnerable Code ```python # Create a context that does not verify SSL ctx = ssl.create_default_context() ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE req = urllib.request.Request(url, headers={'User-Agent': 'Mozilla/5'}) try: resp = urllib.request.urlopen(req, context=ctx, timeout=10) data = json.loads(resp.read().decode('utf-8')) return data except Exception as e: # If SSL fails, try HTTP url_http = url.replace('https://', 'http://') req = urllib.request.Request(url_http, headers={'User-Agent': 'Mozilla/5'}) resp = urllib.request.urlopen(req, timeout=10) data = json.loads(resp.read().decode('utf-8')) return data ``` ### Technical Analysis The script explicitly disables both TLS certificate verification and hostname validation. Consequently, HTTPS encrypts the connection but does not authenticate the Open-Meteo server. An attacker with an on-path network position can present an arbitrary certificate, impersonate the API, and return manipulated weather data. The broad `except Exception` handler further weakens transport security by retrying the request over plaintext HTTP after any exception. This downgrade is not limited to certificate or TLS failures; network errors, response decoding failures, JSON parsing errors, and other runtime exceptions can all trigger it. The fallback request provides neither server authentication nor transport confidentiality or integrity. The API response is also consumed without validating its schema, list lengths, or value types. A forged response could therefore supply misleading values or malformed structures that cause exceptions during report generation. ### Attack Path 1. A user invokes the weather Skill while connected throu ...[truncated 1476 chars]
- Remediation
- ## Remediation Suggestions 1. Preserve Python's default certificate and hostname verification. Remove `ctx.check_hostname = False` and `ctx.verify_mode = ssl.CERT_NONE`, or call `urlopen` without a custom SSL context. 2. Remove the plaintext HTTP fallback entirely. If a verified HTTPS request fails, return a controlled error rather than downgrading transport security. 3. Replace `except Exception` with narrowly scoped handling for expected network, timeout, decoding, and JSON errors. Do not interpret unrelated exceptions as TLS failures. 4. Validate the response before use. Confirm that `daily` is an object, all required fields exist, arrays contain the expected number of entries, and values have appropriate types and ranges. 5. Handle API and validation failures gracefully without exposing stack traces or presenting unverified data as authentic. 6. Keep the existing request timeout and consider limiting response size before JSON parsing to reduce denial-of-service exposure. A secure request pattern would retain verified HTTPS and fail closed: ```python req = urllib.request.Request(url, headers={'User-Agent': 'Mozilla/5'}) try: with urllib.request.urlopen(req, timeout=10) as resp: data = json.loads(resp.read().decode('utf-8')) except (urllib.error.URLError, TimeoutError, UnicodeDecodeError, json.JSONDecodeError) as exc: raise RuntimeError("Unable to retrieve verified weather data") from exc # Validate the response schema and values before returning it. return data ```
