T09 · Insecure Skill Coding Practices
- Location
bin/run.mjs:221- Finding
API Access Token Exposed Through URL Query Parameters
- Content
View full analysis
Vulnerability Details
File Location:
bin/run.mjs, lines 24–31, 64–67, and 221–229
Vulnerability Type: Credential exposure through URL query parameters
Risk Level: MediumVulnerable Code
The operation manifest defines the access token as a query parameter:
js { "defaultValue": null, "description": "Access token for the API.", "enumValues": [], "location": "query", "name": "token", "required": true, "schemaType": "string" }The token is injected into the parameter collection before all query parameters are added to the request URL:
js const params = parseParams(args.paramsJson); applyDefaults(operation, params); injectToken(operation, params, args.token); validateRequired(operation, params); const baseUrl = manifest.baseUrl; const url = new URL(operation.path, ensureBaseUrl(baseUrl)); applyPathParams(operation, params, url); applyQueryParams(operation, params, url);The query-parameter sink converts the token to a string and appends it directly to the URL:
js function appendValue(searchParams, name, value) { if (Array.isArray(value)) { for (const item of value) { appendValue(searchParams, name, item); } return; } if (value && typeof value === "object") { searchParams.append(name, JSON.stringify(value)); return; } searchParams.append(name, String(value)); }Technical Analysis
injectToken()places the JustOneAPI credential inparams.token. Because the manifest declarestokenwithlocation: "query",applyQueryParams()ultimately passes it toappendValue(), producing a request URL equivalent to:text https://api.justoneapi.com/api/bilibili/get-video-detail/v2?token=<secret>&bvid=<video-id>HTTPS protects the request from passive interception while it is in transit, but it does not prevent the complete URL from being retaine ...[truncated 2291 chars]
- Remediation
View remediation
Remediation Suggestions
-
Change the API authentication contract to accept the token in a request header, preferably:
js const requestInit = { headers: { "accept": "application/json", "authorization": `Bearer ${args.token}`, }, method: operation.method, }; -
Remove
tokenfrom the operation's query-parameter definitions and ensureapplyQueryParams()can never serialize authentication credentials. -
Reject
tokeninside--params-jsonso callers cannot bypass the protected authentication path. -
Update
generated/operations.json,generated/operations.md, andSKILL.mdto document header-based authentication. -
Configure API gateways, reverse proxies, backend servers, and observability systems to redact existing
tokenquery parameters while compatibility with the old API remains necessary. -
Avoid logging complete request URLs or command-line arguments containing secrets.
-
Rotate tokens that may already have been retained in URL logs and apply short expiration periods and least-privilege scopes.
-
Add automated tests asserting that serialized request URLs never contain the token value.
-
