T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/kanbn_todo.py:54
- Finding
- Unvalidated API Base URL Enables Credential and Personal Data Exfiltration## Vulnerability Details **File Location**: `scripts/kanbn_todo.py:54-91`, `scripts/kanbn_todo.py:117-129`, and `scripts/kanbn_todo.py:327-332` **Vulnerability Type**: Attacker-controlled network destination for authenticated requests **Risk Level**: High The client accepts an arbitrary API base URL from a command-line argument, environment variable, or `~/.bashrc`. It then sends the configured bearer token or API key to that destination without validating the URL scheme or hostname. ### Vulnerable Code `scripts/kanbn_todo.py:54-91`: ```python class KanbnClient: def __init__(self, base_url, token=None, api_key=None, timeout=30): self.base_url = base_url.rstrip("/") self.token = token self.api_key = api_key self.timeout = timeout def request(self, method, path, params=None, body=None): query = "" if params: query = "?" + urllib.parse.urlencode(params, doseq=True) url = f"{self.base_url}{path}{query}" headers = { "Accept": "application/json", } # Some Kan.bn PUT endpoints require a JSON content-type even when the # request body is logically empty, so send an empty JSON object there. if body is not None: headers["Content-Type"] = "application/json" data = json.dumps(body).encode("utf-8") elif method.upper() in {"POST", "PUT", "PATCH"}: headers["Content-Type"] = "application/json" data = b"{}" else: data = None if self.token: headers["Authorization"] = f"Bearer {self.token}" if self.api_key: headers["x-api-key"] = self.api_key req = urllib.request.Request(url, data=data, headers=headers, method=method) try: with urllib.request.urlopen(req, timeout=self.timeout) as res: ``` `scripts/kanbn_todo.py:117-129`: ` ...[truncated 3381 chars]
- Remediation
- ## Remediation Suggestions 1. **Restrict the destination by default.** Hard-code `https://kan.bn/api/v1` when the Skill is intended exclusively for the official Kan.bn service. 2. **Validate any required custom endpoint.** Parse the URL with `urllib.parse.urlsplit` and require: - The `https` scheme. - A hostname on an explicit allowlist. - An approved port. - No username or password component. - No fragment. - The expected API path. 3. **Require explicit user approval for custom deployments.** Do not accept a custom endpoint solely from ambient configuration when credentials will be attached. 4. **Protect redirect handling.** Disable automatic redirects or validate every redirect target before following it. Never forward authentication headers across origins. 5. **Remove the `~/.bashrc` fallback.** Shell startup files are an unnecessarily broad and mutable source for security-sensitive endpoint and credential configuration. Prefer process-scoped environment variables or a permission-restricted credential store. 6. **Discourage command-line credentials.** Values passed through `--token` or `--api-key` may be exposed through process listings or shell history. Prefer environment variables, standard input, or an operating-system credential store. 7. **Fail closed.** Reject invalid or unapproved destinations before constructing a request or loading authentication headers. 8. **Add security tests.** Verify rejection of plaintext HTTP, unrelated domains, embedded credentials, unexpected ports, and cross-origin redirects.
