T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/wait_for_task.py:34
- Finding
- API Token Exposed in HTTP Query Strings During Task Polling<![CDATA[ ## Vulnerability Details **File Location**: `scripts/wait_for_task.py`, lines 34–39, 106–112, and 131–136 **Vulnerability Type**: Sensitive credential exposure through URL query parameters **Risk Level**: High ### Complete Code Snippet ```python def request_json(endpoint, params, api_key, timeout): url = endpoint + "?" + urllib.parse.urlencode(params) request = urllib.request.Request(url, method="GET") try: with urllib.request.urlopen(request, timeout=timeout) as response: content = response.read() ``` The function is called with the API token inside `params`: ```python payload = request_json( STATUS_ENDPOINT, {"api_key": api_key, "task_id": task_id}, api_key, request_timeout, ) ``` The same behavior is used when downloading results: ```python return request_json( DOWNLOAD_ENDPOINT, {"api_key": api_key, "task_id": task_id, "type": "json"}, api_key, request_timeout, ) ``` ### Technical Analysis The Dataify API token is incorporated directly into the request URL as an `api_key` query parameter. Although the request uses HTTPS, HTTPS does not prevent the URL from being recorded at either endpoint of the connection. Query strings may be retained by: - Dataify web-server access logs - Reverse proxies and load balancers - Local or enterprise HTTP debugging tools - Monitoring and observability platforms - Exception and request telemetry - Browser or networking history if the URL is copied or reused - Security appliances that record complete request targets The response-body redaction performed later by the function does not protect the request URL: ```python if api_key: text = text.replace(api_key, "<redacted>") ``` This only modifies response text after it has been received. It does not remove the token from proxy, server, or client-side request logs. ### Attack Path 1. A user configures a valid `DATAIFY_API_TOKEN`. 2. The Skill submits a task and begins polling its status. 3. ...[truncated 1017 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Move the API token into an HTTP 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", ) ``` 2. Keep only non-secret values such as `task_id` and `type` in the query string. 3. Ensure exception messages never include the full request URL or request headers. 4. Configure server, proxy, and application logs to redact authorization headers. 5. If the Dataify endpoint currently requires `api_key` in the query string: - Request or implement header-based authentication. - Disable query-string logging on all participating infrastructure. - Restrict log access and retention. - Rotate affected tokens after deployment of the fix. 6. Add automated tests asserting that generated request URLs never contain the API token. ]]>
