T09 · Insecure Skill Coding Practices
- Location
bin/run.mjs:18- Finding
Authentication token exposed through command-line arguments and URL query parameters
- Content
View full analysis
Vulnerability Details
File Location:
bin/run.mjs:18-26,bin/run.mjs:67-89,bin/run.mjs:139-148,bin/run.mjs:176-187, andbin/run.mjs:219-241; related usage guidance appears atSKILL.md:41-49
Vulnerability Type: Authentication credential exposure
Risk Level: MediumThe Skill requires an API token and legitimately sends it to the fixed HTTPS host
api.justoneapi.com. However, the token is accepted as a command-line argument and then transmitted as a URL query parameter.Relevant parameter declaration:
js { "defaultValue": null, "description": "User authentication token.", "enumValues": [], "location": "query", "name": "token", "required": true, "schemaType": "string" },Relevant request construction and transmission:
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); const requestInit = { headers: { "accept": "application/json", }, method: operation.method, }; if (operation.requestBody && params.body !== undefined) { requestInit.body = JSON.stringify(params.body); requestInit.headers["content-type"] = operation.requestBody.contentType || "application/json"; } let response; try { response = await fetch(url, requestInit);Relevant command-line parsing and token injection:
js if (flag === "--token") { parsed.token = value; index += 1; continue; }js function injectToken(operation, params, cliToken) { const tokenParam = operation.parameters.find((parameter) => parameter.name === "token"); if (!token ...[truncated 3934 chars]- Remediation
View remediation
Remediation Suggestions
-
Use an authorization header: Change the API contract and client implementation to send the credential in an HTTP header, preferably:
js const requestInit = { method: operation.method, headers: { "accept": "application/json", "authorization": `Bearer ${token}`, }, };Do not add the token to
URL.searchParams. -
Read the token directly from the environment: Replace the documented
--tokenargument withprocess.env.JUST_ONE_API_TOKENso the secret is not placed in the command-line argument vector.js const token = process.env.JUST_ONE_API_TOKEN; if (!token) { fail("JUST_ONE_API_TOKEN is required."); } -
Reject token values in general parameters: Prevent callers from supplying
tokenthrough--params-json, ensuring that credentials use only the dedicated secure authentication path. -
Apply log redaction: Configure client diagnostics, API gateways, proxies, application servers, tracing platforms, and monitoring systems to redact
tokenquery parameters and authorization headers. -
If query authentication cannot be changed: Clearly document the residual exposure, avoid printing or logging the constructed URL, use short-lived and narrowly scoped tokens, restrict access to infrastructure logs, and establish token rotation and revocation procedures.
-
Rotate potentially exposed credentials: Revoke and replace tokens that may already have appeared in process telemetry or URL logs.
-
