T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/analyze-headers.py:81
- Finding
- TLS Certificate and Hostname Verification Disabled<![CDATA[ ## Vulnerability Details **File Location**: `scripts/analyze-headers.py`, lines 81-119 **Vulnerability Type**: Improper Certificate Validation **Risk Level**: Medium ### Vulnerable Code ```python def fetch_headers(url, timeout=10, follow=True, user_agent=None): headers = {"User-Agent": user_agent or "Mozilla/5.0 Security Header Analyzer"} if HAS_REQUESTS: resp = requests.get(url, timeout=timeout, allow_redirects=follow, headers=headers, verify=False) return dict(resp.headers), resp.status_code else: import urllib.request import urllib.error ctx = ssl.create_default_context() ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE req = urllib.request.Request(url, headers=headers) try: resp = urllib.request.urlopen(req, timeout=timeout, context=ctx) return dict(resp.headers), resp.status except urllib.error.HTTPError as e: return dict(e.headers), e.code def check_tls(hostname, port=443): try: ctx = ssl.create_default_context() ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE with socket.create_connection((hostname, port), timeout=5) as sock: with ctx.wrap_socket(sock, server_hostname=hostname) as ssock: cert = ssock.getpeercert() cipher = ssock.cipher() return { "protocol": ssock.version(), "cipher": cipher[0] if cipher else "Unknown", "cipher_bits": cipher[2] if cipher else 0, "cert_subject": dict(x[0] for x in cert.get("subject", ())), "cert_issuer": dict(x[0] for x in cert.get("issuer", ())), "cert_expiry": cert.get("notAfter", "Unknown"), } except Exception as e: return {"error": str(e)} ``` ### Technical Analysis Every supported HTTPS connection path disables cer ...[truncated 2527 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Enable certificate and hostname verification by default: - Remove `verify=False` from `requests.get()`, or explicitly use `verify=True`. - Use `ssl.create_default_context()` without changing `check_hostname` or `verify_mode`. 2. Preserve secure defaults in both network backends: ```python resp = requests.get( url, timeout=timeout, allow_redirects=follow, headers=headers, verify=True, ) ``` ```python ctx = ssl.create_default_context() resp = urllib.request.urlopen(req, timeout=timeout, context=ctx) ``` 3. Make TLS validation part of the TLS report. Distinguish and report: - Certificate-authority trust failures. - Hostname mismatches. - Expired or not-yet-valid certificates. - Missing or malformed certificate data. - Negotiated protocol and cipher security separately from certificate validity. 4. If scanning servers with invalid certificates is a necessary feature, add an explicit `--insecure` option rather than disabling validation unconditionally. The option should: - Default to disabled. - Display a prominent warning. - Mark all affected output as unverified. - Avoid presenting the results as authoritative TLS validation. 5. For comprehensive diagnostics, first perform a verified connection. If it fails and insecure inspection was explicitly authorized, perform a separate unverified connection solely to collect diagnostic certificate details while preserving the original validation failure in the report. 6. Add automated tests confirming rejection of self-signed, expired, and hostname-mismatched certificates under the default configuration. ]]>
