T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/wait_for_task.py:105
- Finding
- API Token Exposed in HTTP Query Strings<![CDATA[ ## Vulnerability Details **File Location**: `scripts/wait_for_task.py:35-39, 105-109, 127-130` **Vulnerability Type**: 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: ``` ```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 The API token is inserted into the query string of status and download requests. Although the connection uses HTTPS, URLs are commonly recorded by reverse proxies, API gateways, server access logs, monitoring systems, exception telemetry, and debugging tools. The subsequent response-body replacement: ```python if api_key: text = text.replace(api_key, "<redacted>") ``` does not protect the outbound request URL or infrastructure logs. This implementation also conflicts with the project's documented authentication contract, which requires `Authorization: Bearer <environment value>`. ### Attack Path 1. A legitimate user runs `wait_for_task.py` or a Builder workflow that calls `complete_task()`. 2. The script sends requests such as `/task_status?api_key=TOKEN&task_id=...`. 3. An operator, compromised monitoring account, log collector, proxy administrator, or other party with URL-log access obtains the complete request URL. 4. The party extracts the API token from the `api_key` parameter. 5. The exposed token is reused against Dataify endpoints until it is revoked or expires. ### Impact Assessment Successful exploitation exposes the privileges assigned to the Da ...[truncated 326 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Remove `api_key` from all URL query parameters. - Send the credential through an HTTP authorization header: ```python request = urllib.request.Request( url, headers={"Authorization": "Bearer {}".format(api_key)}, method="GET", ) ``` - If the remote API cannot accept authorization headers, prefer an authenticated POST request with the credential outside the URL and confirm that request bodies are excluded from logs. - Ensure error messages, telemetry, debug output, and HTTP tracing redact both raw and `Bearer`-prefixed token values. - Rotate any token that may already have appeared in access logs. - Add tests asserting that generated URLs never contain `DATAIFY_API_TOKEN` or an `api_key` credential parameter. ]]>
