T09 · Insecure Skill Coding Practices
Warning
- Location
- bin/run.mjs:369
- Finding
- API Token Exposed Through Process Arguments and URL Query Parameters<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:43`; `bin/run.mjs:369-372`, `bin/run.mjs:403-411`, and `bin/run.mjs:446-465` **Vulnerability Type**: Credential exposure through command-line arguments and URL query parameters **Risk Level**: Medium ### Vulnerable Code `SKILL.md:43`: ```bash node {baseDir}/bin/run.mjs --operation "<operation-id>" --token "$JUST_ONE_API_TOKEN" --params-json '{"key":"value"}' ``` `bin/run.mjs:369-372`: ```js if (flag === "--token") { parsed.token = value; index += 1; continue; } ``` `bin/run.mjs:403-411`: ```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; } ``` `bin/run.mjs:446-465`: ```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)); } ``` ### Technical Analysis The documented invocation expands `JUST_ONE_API_TOKEN` into the Node.js process argument vector. On systems where process metadata is visible to other users, monitoring agents, container administrators, or diagnostic tools, the token may be captured while the process is running or from recorded process telemetry. The helper subsequently assi ...[truncated 1993 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Remove the secret-bearing `--token` command-line option and read the token directly from the environment: ```js const token = process.env.JUST_ONE_API_TOKEN; if (!token) { fail("JUST_ONE_API_TOKEN is required."); } ``` 2. If supported by JustOneAPI, transmit the token in an authorization header instead of the URL: ```js const requestInit = { method: operation.method, headers: { accept: "application/json", authorization: `Bearer ${token}`, }, }; ``` 3. Remove `token` from the user-controlled parameter object so callers cannot override or accidentally serialize credentials through `--params-json`. 4. If the upstream API strictly requires query-string authentication: - Redact the `token` parameter before logging URLs or request diagnostics. - Configure proxies, gateways, servers, and observability systems not to retain query strings for these routes. - Avoid including complete request URLs in exceptions. - Use short-lived, narrowly scoped tokens and support prompt rotation and revocation. - Explicitly document the unavoidable residual query-string exposure. 5. Update `SKILL.md` to use an environment-only invocation without a token argument: ```bash JUST_ONE_API_TOKEN="..." node {baseDir}/bin/run.mjs \ --operation "<operation-id>" \ --params-json '{"key":"value"}' ``` Prefer setting the variable through a protected runtime secret store rather than inline shell syntax, because inline environment assignments may also be retained in shell or orchestration telemetry. ]]>
