T09 · Insecure Skill Coding Practices
- Location
scripts/wait_for_task.py:35- Finding
API Token Exposed in Task Request URL Query Strings
- Content
View full analysis
Vulnerability Details
File Location:
scripts/wait_for_task.py:35-39, with sensitive call sites atscripts/wait_for_task.py:104-108andscripts/wait_for_task.py:129-134
Vulnerability Type: Credential exposure through URL query parameters
Risk Level: HighVulnerable 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 API key is supplied through
paramsat both task-processing 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 all parameters, includingapi_key, directly into the request URL. Although HTTPS protects the URL while it is in transit, URL query strings are frequently retained by reverse-proxy access logs, API gateway logs, network observability products, exception reports, monitoring infrastructure, and server-side request telemetry.The response redaction performed later in the function only replaces the API key if it appears in the response body. It does not protect the outgoing request URL or any infrastructure logs that record it.
This behavior also conflicts with the package's documented authentication contract, which requires
DATAIFY_API_TOKENto be transmitted as an HTTP Bearer credential. Authentication is necessary for the declared functionality, but exposing the credential in a URL exceeds the minimum safe disclosure required.Attack Path
- A user submits a Dataify Bui ...[truncated 1014 chars]
- Remediation
View remediation
Remediation Suggestions
-
Remove
api_keyfrom all status and download query-parameter dictionaries. -
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 {}".format(api_key)}, method="GET", ) -
Keep only non-secret values, such as
task_idand response type, in the query string. -
Confirm that Dataify's task endpoints support Bearer authentication and update the integration contract consistently.
-
Configure proxies, API gateways, and application telemetry to redact authorization headers.
-
Rotate any token that may already have appeared in request logs.
-
Add automated tests asserting that generated URLs never contain the token or an
api_keyparameter.
-
