T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/wait_for_task.py:35
- Finding
- API Token Exposed in HTTP Query Strings## Vulnerability Details **File Location**: `scripts/wait_for_task.py:35-37`, `scripts/wait_for_task.py:102-107`, and `scripts/wait_for_task.py:126-132` **Vulnerability Type**: Sensitive credential exposure through URL query parameters **Risk Level**: Medium ### Vulnerable Code ```python def request_json(endpoint, params, api_key, timeout): url = endpoint + "?" + urllib.parse.urlencode(params) request = urllib.request.Request(url, method="GET") ``` ```python payload = request_json( STATUS_ENDPOINT, {"api_key": api_key, "task_id": task_id}, api_key, request_timeout, ) ``` ```python if status == SUCCESS_STATUS: return request_json( DOWNLOAD_ENDPOINT, {"api_key": api_key, "task_id": task_id, "type": "json"}, api_key, request_timeout, ) ``` ### Technical Analysis The API token is placed in the `api_key` query parameter for both task-status and result-download requests. `request_json()` serializes this parameter into the request URL. HTTPS encrypts the URL while it is in transit, but it does not prevent URLs from being captured by endpoint access logs, reverse proxies, network monitoring products, application telemetry, browser-like debugging facilities, or error-reporting systems. Query strings are commonly logged in their entirety. The subsequent replacement of the API key in the response body does not protect the request URL: ```python if api_key: text = text.replace(api_key, "<redacted>") ``` This redaction occurs only after the response has been received and therefore cannot remove the credential from infrastructure logs generated while handling the request. The network operation itself is necessary for task completion, but transmitting the credential in a URL exceeds the minimum exposure required. Other project clients already use an `Authorization: Bearer` header, demonstrating that header-based authentica ...[truncated 1203 chars]
- Remediation
- ## Remediation Suggestions 1. Remove `api_key` from all query parameter dictionaries. 2. Transmit the credential through an authorization header: ```python request = urllib.request.Request( endpoint + "?" + urllib.parse.urlencode(params), headers={"Authorization": "Bearer {}".format(api_key)}, method="GET", ) ``` 3. Ensure redirect handling does not forward the authorization header to a different origin. Reject redirects whose scheme or hostname differs from the expected Dataify endpoint. 4. Retain only `task_id` and `type` as query parameters. 5. Add tests asserting that generated URLs never contain the token or an `api_key` parameter. 6. Review and sanitize existing proxy, gateway, and application logs, then rotate credentials that may already have been recorded. 7. Apply consistent bearer-token normalization before constructing the header so an existing `Bearer ` prefix is not duplicated.
