T09 · Insecure Skill Coding Practices
- Location
bin/run.mjs:198- Finding
API Token Exposed Through Process Arguments and URL Query Parameters
- Content
View full analysis
Vulnerability Details
File Location:
SKILL.md:44-52;bin/run.mjs:161-170, 198-209, 241-263;generated/operations.json:16-24;generated/operations.md:18
Vulnerability Type: Credential exposure through command-line arguments and URL query parameters
Risk Level: MediumThe documented invocation passes the API token as a command-line argument:
bash node {baseDir}/bin/run.mjs --operation "searchDouyinUserV2" --token "$JUST_ONE_API_TOKEN" --params-json '{"keyword":"<keyword>"}'The command-line parser stores the supplied token:
javascript if (flag === "--token") { parsed.token = value; index += 1; continue; }The token is then inserted into the request parameters:
javascript 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; }Because the operation declares the token as a query parameter, the generic query builder appends it to the request URL:
javascript 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 ...[truncated 2823 chars]- Remediation
View remediation
Remediation Suggestions
-
Read the credential directly from
process.env.JUST_ONE_API_TOKENinstead of accepting it through--token. This prevents routine exposure through process argument listings. -
Remove or deprecate the
--tokenoption. If temporary compatibility is required, emit a security warning and prioritize the environment variable. -
Use an
Authorizationheader or another non-URL authentication header if JustOneAPI supports one. For example:javascript const token = process.env.JUST_ONE_API_TOKEN; if (!token) { fail("JUST_ONE_API_TOKEN is required."); } const requestInit = { headers: { accept: "application/json", authorization: `Bearer ${token}`, }, method: operation.method, }; -
Remove
tokenfrom the generic query-parameter manifest and ensureapplyQueryParamscan never serialize authentication credentials. -
Reject
tokeninside--params-jsonso callers cannot bypass centralized credential handling. -
If the upstream service strictly requires query-string authentication, document that residual risk and ensure proxies, gateways, application logs, monitoring systems, and error reports redact the
tokenparameter. -
Avoid including complete request URLs in errors or diagnostics. Add automated tests that verify token values do not appear in standard output, standard error, process arguments under the recommended invocation, or application-generated logs.
-
Rotate any token suspected of having been captured in process-monitoring data or URL logs.
-
