T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/wait_for_task.py:34
- Finding
- Dataify API token exposed through URL query parameters<![CDATA[ ## Vulnerability Details **File Location**: `scripts/wait_for_task.py:34-36`, with vulnerable calls at `scripts/wait_for_task.py:104-110` and `scripts/wait_for_task.py:126-132` **Vulnerability Type**: Credential exposure through URL query strings **Risk Level**: High ### Vulnerable Code ```python def request_json(endpoint, params, api_key, timeout): url = endpoint + "?" + urllib.parse.urlencode(params) request = urllib.request.Request(url, method="GET") ``` The status request supplies the API token as an `api_key` query parameter: ```python payload = request_json( STATUS_ENDPOINT, {"api_key": api_key, "task_id": task_id}, api_key, request_timeout, ) ``` The result download request does the same: ```python return request_json( DOWNLOAD_ENDPOINT, {"api_key": api_key, "task_id": task_id, "type": "json"}, api_key, request_timeout, ) ``` ### Technical Analysis The API credential is encoded directly into the request URL instead of being sent in an authorization header. URLs are routinely recorded by HTTP servers, reverse proxies, gateways, observability platforms, network debugging tools, and exception-reporting systems. The following response-body redaction does not mitigate this exposure: ```python if api_key: text = text.replace(api_key, "<redacted>") ``` It only modifies the returned response text. It does not remove the token from the outgoing URL or infrastructure logs. This transmission is unnecessary because other project components already authenticate to Dataify using an `Authorization: Bearer ...` header. ### Attack Path 1. A user configures `DATAIFY_API_TOKEN` and submits or monitors a Dataify task. 2. `wait_for_task()` passes the token in the `api_key` query parameter. 3. `request_json()` constructs a URL containing the plaintext token. 4. A server, proxy, monitoring platform, or diagnostic component records the complete URL. 5. An attacker or unauthorized operator with access to those l ...[truncated 550 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Remove `api_key` from all query-parameter dictionaries. 2. Send the token through the standard authorization header: ```python def request_json(endpoint, params, api_key, timeout): url = endpoint + "?" + urllib.parse.urlencode(params) request = urllib.request.Request( url, headers={"Authorization": "Bearer {}".format(api_key)}, method="GET", ) ``` 3. Update both status and download calls: ```python {"task_id": task_id} ``` ```python {"task_id": task_id, "type": "json"} ``` 4. If the remote API only accepts query-string authentication, request an API change or use a POST body over HTTPS. Until then, explicitly document the exposure and configure all relevant infrastructure to redact `api_key`. 5. Ensure error reporting, access logs, tracing systems, and debug output redact complete request URLs. 6. Rotate tokens that may already have appeared in logs. ]]>
