T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/request_client.py:18
- Finding
- Bearer API credentials can be transmitted over unencrypted HTTP## Vulnerability Details **File Location**: `scripts/request_client.py:18-35, 39-42, 54-63` **Vulnerability Type**: Missing HTTPS enforcement for authenticated API requests **Risk Level**: High ### Vulnerable Code ```python def __init__( self, base_url: str, api_key: str, timeout: int = 30, ) -> None: if not base_url: raise ValueError("base_url 不能为空") if not api_key: raise ValueError("api_key 不能为空") self.base_url = base_url self.api_key = api_key self.timeout = timeout self.session = requests.Session() self.session.headers.update({ "Authorization": f"Bearer {self.api_key}", }) def _build_url(self, path: str) -> str: base_url = self.base_url.rstrip("/") path = path.lstrip("/") return f"{base_url}/{path}" ``` The resulting URL is used without scheme validation: ```python url = self._build_url(path) response = self.session.request( method, url, params=params, data=data, json=json, timeout=self.timeout, **kwargs, ) ``` ### Technical Analysis The client accepts any non-empty `base_url` and unconditionally attaches a bearer API key to its session. It does not parse the URL or require the HTTPS scheme. Consequently, an `http://` base URL is accepted and the `Authorization` header is transmitted without transport encryption. Restricting requests to a user-configured destination does not provide confidentiality or server authenticity. Plain HTTP allows an attacker with a suitable network position to observe or modify traffic. The problem affects every authenticated query and mutation exposed by the client. ### Attack Path 1. A merchant or platform configuration supplies an `RR_CLAW_BASE_URL` beginning with `http://`, whether through error, insecure deployment guidance, or configuration tampering. 2. `RequestClient.__init__` accepts the value because it only checks whether it is empty. 3. The client stores the API key in the session-wide `Authorizat ...[truncated 1032 chars]
- Remediation
- ## Remediation Suggestions 1. Parse `base_url` with `urllib.parse.urlsplit` during initialization. 2. Reject every scheme except `https`. 3. Reject URLs containing embedded usernames or passwords. 4. Require a valid hostname and reject malformed or ambiguous URLs. 5. If local HTTP development is necessary, require an explicit development-only option and restrict it to loopback addresses such as `127.0.0.1` and `::1`. 6. Keep TLS certificate verification enabled and do not permit callers to override it through unrestricted request keyword arguments. 7. Add tests confirming that HTTP, scheme-relative, credential-bearing, and malformed URLs are rejected. 8. Document HTTPS as mandatory for `RR_CLAW_BASE_URL`. Example hardening: ```python from urllib.parse import urlsplit parsed = urlsplit(base_url) if parsed.scheme.lower() != "https": raise ValueError("base_url must use HTTPS") if not parsed.hostname: raise ValueError("base_url must contain a valid hostname") if parsed.username is not None or parsed.password is not None: raise ValueError("base_url must not contain embedded credentials") ```
