T09 · Insecure Skill Coding Practices
- Location
bin/run.mjs:173- Finding
API Token Exposed Through Process Arguments and URL Query Parameters
- Content
View full analysis
Vulnerability Details
File Location:
SKILL.md:40-47;bin/run.mjs:25-32,bin/run.mjs:58-64,bin/run.mjs:173-185, andbin/run.mjs:215-225
Vulnerability Type: Credential exposure through command-line arguments and query-string authentication
Risk Level: MediumThe Skill legitimately requires a JustOneAPI credential to perform its declared Reddit keyword search. However, the credential is passed as a command-line argument and then included in the request URL, creating avoidable exposure beyond the minimum necessary for authentication.
Vulnerable Code
The documented invocation passes the secret through the process command line:
bash node {baseDir}/bin/run.mjs --operation "searchRedditV1" --token "$JUST_ONE_API_TOKEN" --params-json '{"keyword":"<keyword>"}'The operation declares the token as a query parameter:
js { "defaultValue": null, "description": "Access token for this API service.", "enumValues": [], "location": "query", "name": "token", "required": true, "schemaType": "string" }The CLI token is copied into the request 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 parameters declared with
location === "query", including the token, are appended to the 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) ...[truncated 2692 chars]- Remediation
View remediation
Remediation Suggestions
-
Read the credential directly from
process.env.JUST_ONE_API_TOKENinstead of requiring it through--token. This prevents routine exposure through process argument inspection:js const token = process.env.JUST_ONE_API_TOKEN; if (!token) { fail("JUST_ONE_API_TOKEN is required.", { operationId: operation.operationId, }); } -
Prefer an authorization header if supported by JustOneAPI:
js const requestInit = { headers: { accept: "application/json", authorization: `Bearer ${token}`, }, method: operation.method, }; -
Remove the token from the operation's query parameters when header-based authentication is available. Do not permit users to supply
tokeninside--params-json. -
If the backend only supports query-string authentication, request or implement a header-based authentication option. Until then:
- Never print or serialize the complete request URL.
- Configure proxies, API gateways, and observability systems to redact the
tokenquery parameter. - Avoid including URLs containing credentials in exceptions or debug output.
- Use short-lived, narrowly scoped tokens where supported.
- Disable unnecessary request and command-line telemetry.
-
Update
SKILL.mdso the recommended invocation relies on the environment variable without expanding it into a command-line argument. -
Rotate any token that may already have been retained in process telemetry, shell history, gateway logs, or monitoring systems.
-
