T09 · Insecure Skill Coding Practices
- Location
qrcode.py:18- Finding
API Credential Exposed in URL Query String
- Content
View full analysis
Vulnerability Details
File Location:
qrcode.py, lines 18–23
Vulnerability Type: API credential disclosure through URL query parameters
Risk Level: Mediumpython 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_apifunction placesJISU_API_KEYintoall_paramsand passes that dictionary torequests.getthrough theparamsargument. Therequestslibrary 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
- A user or automated agent invokes the
generate,read, ortemplatecommand. - The script reads the reusable credential from the
JISU_API_KEYenvironment variable. _call_apiinserts that credential into the GET request's query string.- The complete request URL is recorded by the API provider, a reverse proxy, monitoring infrastructure, or application diagnostics.
- An attacker or unauthorized operator with access to those records extracts the
appkeyvalue. - The attacker submits requests directly to JisuAPI using the recovered credential.
Exploitation requires access to ...[truncated 671 chars]
- A user or automated agent invokes the
- Remediation
View remediation
Remediation Suggestions
-
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) -
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.
-
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.
-
Rotate the currently configured API key if request URLs may already have been logged.
-
Monitor provider usage for unexpected requests, quota spikes, and calls from unrecognized source addresses.
-
Where supported, configure provider-side restrictions such as API-level scope, source-IP allowlisting, spending limits, and rate limits.
-
