T09 · Insecure Skill Coding Practices
- Location
bin/run.mjs:31- Finding
API Access Token Exposed in URL Query String
- Content
View full analysis
Vulnerability Details
File Location:
bin/run.mjs:31-38, 73-80, 92-96, 216-225
Vulnerability Type: Sensitive credential exposure through URL query parameters
Risk Level: MediumVulnerable Code
js { "defaultValue": null, "description": "Access token for this API service.", "enumValues": [], "location": "query", "name": "token", "required": true, "schemaType": "string" }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);js let response; try { response = await fetch(url, requestInit); } catch (error) { fail("Network request failed.", { cause: error instanceof Error ? error.message : String(error), operationId: operation.operationId, }); }js function applyQueryParams(operation, params, url) { for (const parameter of operation.parameters.filter((item) => item.location === "query")) { const value = params[parameter.name]; if (value === undefined) { continue; } appendValue(url.searchParams, parameter.name, value); } }Technical Analysis
The operation manifest classifies the API access token as a query parameter. The program copies the token supplied through
--tokenintoparams.token, after whichapplyQueryParams()serializes it intourl.searchParams. The resulting request has the effective form:text https://api.justoneapi.com/api/xiaohongshu/share-url-transfer/v1?token=<credential>&shareUrl=<user-input>HTTPS protects the request from passive interception while it is in transit, but it does not prevent the complete URL from being retained by the de ...[truncated 2136 chars]
- Remediation
View remediation
Remediation Suggestions
-
Change the API authentication contract to accept the credential in an authorization header rather than the URL:
js const requestInit = { headers: { accept: "application/json", authorization: `Bearer ${args.token}`, }, method: operation.method, }; -
Remove
tokenfrom the operation's query-parameter definition and ensureapplyQueryParams()cannot serialize authentication credentials:js function applyQueryParams(operation, params, url) { for (const parameter of operation.parameters.filter( (item) => item.location === "query" && item.name !== "token" )) { const value = params[parameter.name]; if (value !== undefined) { appendValue(url.searchParams, parameter.name, value); } } } -
Prefer reading the token directly from
JUST_ONE_API_TOKENinstead of requiring it as a command-line argument. Command-line values may be visible in process listings, shell history, job telemetry, or orchestration metadata. -
Redact tokens, authorization headers, and sensitive query parameters from application logs, proxy logs, exception reports, distributed traces, and monitoring telemetry.
-
If the remote API only supports query-string authentication, document this residual risk explicitly, use narrowly scoped and short-lived tokens, rotate credentials regularly, and configure every involved proxy and server not to retain query strings.
-
Update
SKILL.md,generated/operations.json, andgenerated/operations.mdafter changing the authentication contract so the documentation and generated metadata remain consistent with the hardened implementation.
-
