T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/wait_for_task.py:34
- Finding
- Dataify API Token Exposed in URL Query Parameters<![CDATA[ ## Vulnerability Details **File Location**: `scripts/wait_for_task.py:34-39`, with sensitive parameters supplied at `scripts/wait_for_task.py:102-107` and `scripts/wait_for_task.py:127-132` **Vulnerability Type**: Credential exposure through URL query strings **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") try: with urllib.request.urlopen(request, timeout=timeout) as response: content = response.read() ``` The function is called with the API token included in `params`: ```python payload = request_json( STATUS_ENDPOINT, {"api_key": api_key, "task_id": task_id}, api_key, request_timeout, ) ``` The same behavior occurs 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 encoded into the request URL as an `api_key` query parameter. Although HTTPS protects the request while it is in transit, URLs are commonly captured by reverse-proxy logs, application access logs, network monitoring products, exception telemetry, debugging tools, and process diagnostics. The response redaction performed later by the script does not protect the outbound request URL. The token can therefore be exposed outside the intended authentication boundary. Authentication is necessary for task monitoring, but transmitting a reusable account credential in the URL is not the minimum-risk implementation. Authentication should be placed in an HTTP header whenever the service supports it. ### Attack Path 1. A user invokes the normal task-completion workflow with `DATAIFY_API_TOKEN` configured. 2. The script creates a URL such as `/task_status?api_key=SECRET&task_id=...`. 3. A server, proxy, tele ...[truncated 615 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Send the credential through an authorization header: ```python request = urllib.request.Request( url, headers={"Authorization": f"Bearer {api_key}"}, method="GET", ) ``` 2. Keep only non-secret values such as `task_id` and `type` in the query string. 3. If the Dataify API currently requires query authentication, change the API contract or use a short-lived, task-scoped download token instead of the reusable account token. 4. Configure clients, proxies, and application servers to suppress query-string logging. 5. Ensure exception messages and telemetry never serialize request objects containing credentials. 6. Rotate any token that may already have appeared in URL or proxy logs. ]]>
