T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/wait_for_task.py:36
- Finding
- API Token Exposed in HTTP GET Query Strings<![CDATA[ ## Vulnerability Details **File Location**: `scripts/wait_for_task.py:36-39`, with sensitive call sites at `scripts/wait_for_task.py:98-103` and `scripts/wait_for_task.py:130-134` **Vulnerability Type**: Sensitive credential exposure through URL query parameters **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") try: with urllib.request.urlopen(request, timeout=timeout) as response: ``` The API token is included in `params` at both call sites: ```python payload = request_json( STATUS_ENDPOINT, {"api_key": api_key, "task_id": task_id}, api_key, request_timeout, ) ``` ```python return request_json( DOWNLOAD_ENDPOINT, {"api_key": api_key, "task_id": task_id, "type": "json"}, api_key, request_timeout, ) ``` ### Technical Analysis `request_json()` URL-encodes the supplied parameters and appends them directly to the endpoint. Consequently, `DATAIFY_API_TOKEN` becomes part of the complete request URL for task-status and result-download requests. Although HTTPS encrypts the request in transit, it does not prevent the complete URL from being recorded by components such as: - Reverse-proxy and web-server access logs - API gateways - Network monitoring or application performance monitoring systems - Browser or HTTP debugging tools - Exception and diagnostic telemetry - Request tracing systems The response-body redaction performed later by the function does not protect the token already included in the request URL. Sending a credential in the URL also exceeds the minimum disclosure necessary because the other scripts already demonstrate that Dataify supports bearer authorization headers. ### Attack Path 1. A user configures a valid `DATAIFY_API_TOKEN`. 2. The user submits a task or runs `wait_for_task.py`. 3. The polling and download logic pl ...[truncated 761 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Remove `api_key` from all URL query parameters. 2. Send the credential exclusively through an 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 " + api_key}, method="GET", ) ``` 3. Update the status and download calls so their parameter dictionaries contain only non-secret values such as `task_id` and `type`. 4. Configure the server to reject query-string API credentials. 5. Redact authorization headers and sensitive query keys in gateway, proxy, and telemetry configurations. 6. Review historical access logs for exposed tokens and rotate any credential that may have been recorded. 7. Add tests asserting that generated request URLs never contain the token or an `api_key` parameter. ]]>
