T09 · Insecure Skill Coding Practices
- Location
bin/run.mjs:18- Finding
API Token Exposed Through Command-Line Arguments and URL Query Parameters
- Content
View full analysis
Vulnerability Details
File Location:
SKILL.md:51;bin/run.mjs:18-24, 132, 148, 235-246, 278-288;generated/operations.json:13-19;generated/operations.md:17
Vulnerability Type: Credential exposure through process arguments and URL query strings
Risk Level: MediumVulnerable Code
The operation defines the authentication token as a query parameter:
js { "defaultValue": null, "description": "User authentication token.", "enumValues": [], "location": "query", "name": "token", "required": true, "schemaType": "string" },The command-line token is copied into the query parameters:
js function injectToken(operation, params, cliToken) { const tokenParam = operation.parameters.find((parameter) => parameter.name === "token"); if (!tokenParam || params.token !== undefined) { return; } if (!cliToken) { fail("--token is required for this operation.", { operationId: operation.operationId, }); } params.token = cliToken; }All query parameters, including the token, are appended to the request URL:
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); } } 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)); }The resulting URL is sent to the fixed remote service:
js applyQuer ...[truncated 3411 chars]- Remediation
View remediation
Remediation Suggestions
- Remove command-line token handling. Read the credential directly from
process.env.JUST_ONE_API_TOKENso it is not expanded into the process argument vector. Reject explicit tokens inside--params-json. - Use an authorization header. If supported by JustOneAPI, transmit the credential using an appropriate header, such as
Authorization: Bearer ..., and removetokenfrom the operation's query-parameter manifest. - Update generated definitions and documentation. Change
generated/operations.json,generated/operations.md, andSKILL.mdso they no longer classify or demonstrate the token as a URL query parameter or CLI argument. - Prevent accidental logging. Never print the request URL, authorization header, environment variable, or full request configuration. Add centralized redaction for fields named
token,authorization,apiKey, or equivalent. - Harden unavoidable query authentication. If the upstream API mandates a query token, configure clients, gateways, proxies, access logs, APM products, and error-reporting systems to redact the
tokenparameter. Avoid redirects and keep the fixed HTTPS destination. - Limit credential impact. Use short-lived, narrowly scoped tokens with rate limits and quota alerts. Provide a documented revocation and rotation procedure for suspected disclosure.
- Add regression tests. Verify that the token never appears in command arguments, generated URLs, standard output, standard error, exception details, or captured logs.
- Remove command-line token handling. Read the credential directly from
