T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/query_usage.py:34
- Finding
- API Key Exposed in URL Query String## Vulnerability Details **File Location**: `scripts/query_usage.py`, lines 34-36 **Vulnerability Type**: Sensitive information transmitted in a query string **Risk Level**: High ### Vulnerable Code ```python def query_usage(base_url: str, api_key: str, timeout: int) -> dict: params = urlencode({"key": api_key}) url = f"{normalize_base_url(base_url)}{LOG_ENDPOINT}?{params}" return request_json(url, api_key, timeout) ``` ### Technical Analysis The API key is included in the request URL as the `key` query parameter. The same credential is also transmitted in the `Authorization` header by `request_json()`, making the query-string transmission redundant where Bearer authentication is supported. URLs are routinely recorded by web servers, reverse proxies, gateways, monitoring systems, browser or network tooling, and access-log aggregation services. Consequently, even when HTTPS protects the request in transit, the complete key may remain stored in logs accessible to operators or other systems. This conflicts with the Skill's stated objective of protecting the full API key and exceeds the minimum data exposure needed for a read-only usage query. ### Attack Path 1. A user invokes the Skill with a valid API key. 2. The script constructs `/api/log/token?key=<API_KEY>`. 3. The request passes through the destination server or an intermediary reverse proxy. 4. The full request URL is retained in an access, telemetry, or diagnostic log. 5. An attacker, unauthorized operator, or compromised logging system retrieves the key. 6. The attacker submits requests using the exposed credential. ### Impact Assessment An exposed key grants the attacker the API permissions assigned to that credential. Depending on server-side authorization, this may include reading quota and usage records or invoking other API functions available to the key. The issue does not directly grant local operating-system privileges, but i ...[truncated 93 chars]
- Remediation
- ## Remediation Suggestions - Remove the API key from the query string and authenticate exclusively through the `Authorization: Bearer` header. - Change the usage request to construct the endpoint without secret parameters: ```python def query_usage(base_url: str, api_key: str, timeout: int) -> dict: url = f"{normalize_base_url(base_url)}{LOG_ENDPOINT}" return request_json(url, api_key, timeout) ``` - If the remote API contract unavoidably requires a query-string key: - Clearly warn users that the destination and its intermediaries may log the credential. - Use a short-lived, read-only, narrowly scoped token. - Configure servers, proxies, observability systems, and error handlers to redact the `key` parameter. - Avoid printing or including complete request URLs in diagnostics. - Prefer changing the server API to accept header-based authentication.
