T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/caprover.py:27
- Finding
- Disabled TLS Verification Exposes CapRover Administrator Credentials and Privileged API Traffic<![CDATA[ ## Vulnerability Details **File Location**: `scripts/caprover.py:27-29` and `scripts/caprover.py:52` **Related Documentation**: `SKILL.md:17-18`, `references/api.md:6` **Vulnerability Type**: Improper TLS certificate and hostname validation **Risk Level**: High ### Vulnerable Code ```python def _make_ctx(): ctx = ssl.create_default_context() ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE return ctx ``` The insecure SSL context is subsequently used for all API requests: ```python req = urllib.request.Request(f"{self.base}{path}", data=body, headers=headers) try: resp = urllib.request.urlopen(req, context=self._ctx, timeout=timeout) return json.loads(resp.read()) ``` The same insecure behavior is recommended in `SKILL.md`: ```python ctx = ssl.create_default_context() ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE # self-signed cert on CapRover is common ``` It is also explicitly recommended in `references/api.md`: ```markdown SSL: often self-signed → disable verification in HTTP clients ``` ### Technical Analysis The helper creates a TLS context that accepts certificates from any issuer and does not verify whether the certificate belongs to the requested CapRover hostname. HTTPS encryption without peer authentication does not protect against an active man-in-the-middle attacker. This context is used during authentication, where the CapRover administrator password is placed in a JSON request body: ```python def _login(self, password: str) -> str: r = self._call("/api/v2/login", {"password": password}) return r["data"]["token"] ``` It is also used for all subsequent privileged requests carrying the `x-captain-auth` token: ```python tok = token or getattr(self, "token", None) if tok: headers["x-captain-auth"] = tok ``` Consequently, the exposed data may include: - The CapRover administrator password. - The session bearer token. - Application environment variables, which may cont ...[truncated 2431 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Preserve the secure defaults from `ssl.create_default_context()`: ```python def _make_ctx(cafile: str | None = None): ctx = ssl.create_default_context(cafile=cafile) return ctx ``` 2. For private or self-signed CapRover certificates, require an explicit CA certificate: ```python ctx = ssl.create_default_context() ctx.load_verify_locations(cafile="/secure/path/caprover-ca.pem") ``` 3. Keep hostname verification enabled and ensure the CapRover certificate includes the expected DNS name in its Subject Alternative Name extension. 4. Remove instructions from `SKILL.md` and `references/api.md` that recommend globally disabling TLS verification. Replace them with instructions for installing or specifying the private CA. 5. If an insecure development mode must exist, require an explicit option such as `allow_insecure_tls=False`, keep it disabled by default, and display a prominent warning before credentials are transmitted. It should not be used in production or automated deployments. 6. Consider certificate or public-key pinning for tightly controlled CapRover environments where private CA management is not practical. 7. Rotate the CapRover administrator password and invalidate existing session tokens if the helper has previously been used over an untrusted network. ]]>
