T09 · Insecure Skill Coding Practices
Warning
- Location
- main.py:150
- Finding
- API Credentials May Be Transmitted over Unencrypted HTTP## Vulnerability Details **File Location**: `main.py:150`, `main.py:216-218`, `main.py:231-233`, `main.py:284-287`, and `main.py:337-340` **Vulnerability Type**: Plaintext transmission of sensitive credentials **Risk Level**: Medium The provider URL is loaded directly from configuration without requiring HTTPS: ```python base_url = provider.get("baseUrl", "") ``` The unvalidated URL is subsequently used for authenticated Anthropic and OpenAI-compatible requests: ```python headers = {"x-api-key": target.api_key, "anthropic-version": "2023-06-01", "content-type": "application/json"} payload = {"model": target.model, "max_tokens": 256, "stream": False, "messages": [{"role": "user", "content": prompt}]} r = requests.post(f"{target.base_url}/v1/messages", headers=headers, json=payload, timeout=30) ``` ```python headers = {"Authorization": f"Bearer {target.api_key}", "content-type": "application/json"} payload = {"model": target.model, "max_tokens": 32, "stream": False, "messages": [{"role": "user", "content": prompt}]} r = requests.post(f"{target.base_url}/chat/completions", headers=headers, json=payload, timeout=20) ``` ```python headers = {"x-api-key": target.api_key, "anthropic-version": "2023-06-01", "content-type": "application/json"} payload = {"model": target.model, "max_tokens": max_tokens, "stream": True, "messages": [{"role": "user", "content": prompt}]} t_start = time.perf_counter() ``` The corresponding Anthropic streaming request is: ```python with requests.post(f"{target.base_url}/v1/messages", headers=headers, json=payload, stream=True, timeout=timeout) as resp: ``` The OpenAI-compatible streaming request has the same issue: ```python headers = {"Authorization": f"Bearer {target.api_key}", "content-type": "application/json"} payload = {"model": target.model, "max_tokens": max_tokens, "stream": True, "messages": [{"role": "user", "content": prompt}]} t_start = time.perf_counter( ...[truncated 2640 chars]
- Remediation
- ## Remediation Suggestions 1. Parse every provider URL with `urllib.parse.urlparse` and reject malformed URLs. 2. Require the `https` scheme for all remote provider endpoints before constructing a `Target`. 3. If plaintext transport is needed for local development, permit it only through an explicit opt-in flag and only for loopback destinations such as `127.0.0.1`, `::1`, or `localhost`. Display a prominent warning when this exception is used. 4. Reject URLs containing embedded user information, unexpected fragments, or ambiguous host representations. 5. Disable automatic redirects for authenticated requests with `allow_redirects=False`, or validate every redirect target before following it. Require the destination to remain on HTTPS and within the intended trusted origin. 6. Fail closed before reading or attaching the API key if URL validation fails. 7. Document that configuration files containing literal API keys must have restrictive filesystem permissions, while continuing to recommend environment-variable placeholders. 8. Add tests confirming rejection of `http://` remote endpoints, malformed URLs, HTTPS-to-HTTP redirects, and attacker-controlled redirect destinations. 9. Use provider keys with minimum required permissions, spending limits, and rotation procedures to reduce the impact of accidental disclosure.
