T09 · Insecure Skill Coding Practices
Warning
- Location
- bin/run.mjs:306
- Finding
- API Credential Exposure Through URL Query Parameters and Process Arguments## Vulnerability Details **File Location**: `bin/run.mjs:23-31`, `bin/run.mjs:278-286`, `bin/run.mjs:306-313`; related invocation guidance at `SKILL.md:41` **Vulnerability Type**: API credential exposure **Risk Level**: Medium ### Vulnerable Code ```js { "defaultValue": null, "description": "Access token for this API service.", "enumValues": [], "location": "query", "name": "token", "required": true, "schemaType": "string" } ``` ```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; } ``` ```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); } } ``` The documented invocation also passes the credential as a command-line argument: ```bash node {baseDir}/bin/run.mjs --operation "<operation-id>" --token "$JUST_ONE_API_TOKEN" --params-json '{"key":"value"}' ``` ### Technical Analysis The Skill inserts `JUST_ONE_API_TOKEN` into `URL.searchParams`, resulting in requests whose URLs contain the credential as a `token` query parameter. HTTPS protects the request from ordinary passive network interception, but it does not prevent the complete URL from being recorded by the destination service, API gateways, reverse proxies, access logs, observability platforms, debugging tools, or error telemetry. The prescribed command also supplies the secret through `--token`. Command-line arguments may be vi ...[truncated 1994 chars]
- Remediation
- ## Remediation Suggestions 1. Read the credential directly from `process.env.JUST_ONE_API_TOKEN` rather than accepting it through `--token`. 2. If supported by JustOneAPI, transmit the credential in an HTTP authorization header: ```js const token = process.env.JUST_ONE_API_TOKEN; if (!token) { fail("JUST_ONE_API_TOKEN is required."); } const requestInit = { method: operation.method, headers: { accept: "application/json", authorization: `Bearer ${token}`, }, }; ``` 3. Remove `token` from operation query-parameter definitions and prevent callers from supplying a token through `--params-json`. 4. Update `SKILL.md` so the invocation does not include a secret-bearing command-line argument. 5. If the provider only supports query-string authentication: - Retrieve the token directly from the environment. - Configure clients, proxies, gateways, servers, and observability systems to redact the `token` parameter. - Disable storage of complete query strings where possible. - Ensure errors and diagnostics never include the complete request URL. - Use narrowly scoped, short-lived tokens and implement routine rotation. 6. Revoke and replace any token suspected of appearing in process captures, URL logs, or telemetry.
