T09 · Insecure Skill Coding Practices
Warning
- Location
- qrcode.py:18
- Finding
- API Credential Exposed in URL Query String## Vulnerability Details **File Location**: `qrcode.py`, lines 18–23 **Vulnerability Type**: API credential disclosure through URL query parameters **Risk Level**: Medium ```python def _call_api(path: str, appkey: str, params: dict = None): if params is None: params = {} all_params = {"appkey": appkey} all_params.update({k: v for k, v in params.items() if v not in (None, "")}) url = f"{BASE_URL}/{path}" try: resp = requests.get(url, params=all_params, timeout=10) ``` ### Technical Analysis The `_call_api` function places `JISU_API_KEY` into `all_params` and passes that dictionary to `requests.get` through the `params` argument. The `requests` library serializes these parameters into the URL query string, producing a request resembling: ```text https://api.jisuapi.com/qrcode/generate?appkey=REDACTED&text=... ``` HTTPS protects the complete URL while it is transmitted over the network, but it does not prevent the URL from being recorded at either endpoint or by trusted infrastructure. Query strings may appear in application diagnostics, reverse-proxy access logs, API gateway logs, monitoring systems, exception reports, or debugging output. A reusable API credential should therefore not be included in a URL when a safer provider-supported transport is available. ### Attack Path 1. A user or automated agent invokes the `generate`, `read`, or `template` command. 2. The script reads the reusable credential from the `JISU_API_KEY` environment variable. 3. `_call_api` inserts that credential into the GET request's query string. 4. The complete request URL is recorded by the API provider, a reverse proxy, monitoring infrastructure, or application diagnostics. 5. An attacker or unauthorized operator with access to those records extracts the `appkey` value. 6. The attacker submits requests directly to JisuAPI using the recovered credential. Exploitation requires access to ...[truncated 671 chars]
- Remediation
- ## Remediation Suggestions 1. Consult the provider's current API specification and, if supported, send the credential in an authorization header rather than in the URL: ```python headers = {"Authorization": f"Bearer {appkey}"} resp = requests.post(url, json=params, headers=headers, timeout=10) ``` 2. If the provider requires the key in a request body, use a POST request and place it in the body instead of the query string. 3. If JisuAPI only supports query-string authentication, treat this as a provider-imposed residual risk: - Disable or redact query-string logging in clients, proxies, API gateways, monitoring tools, and error-reporting systems. - Ensure logs are access-controlled, encrypted, and retained only as long as necessary. - Never print the prepared request URL or include it in user-visible error messages. - Use a dedicated, least-privileged key for this skill and avoid sharing it with unrelated services. 4. Rotate the currently configured API key if request URLs may already have been logged. 5. Monitor provider usage for unexpected requests, quota spikes, and calls from unrecognized source addresses. 6. Where supported, configure provider-side restrictions such as API-level scope, source-IP allowlisting, spending limits, and rate limits.
