T09 · Insecure Skill Coding Practices
- Location
bin/run.mjs:239- Finding
API Key Exposed Through Process Command-Line Arguments
- Content
View full analysis
Vulnerability Details
File Location:
SKILL.md:60-68,bin/run.mjs:239-255, andbin/run.mjs:308-324
Vulnerability Type: Command-line credential exposure
Risk Level: MediumThe documented invocation passes the API key through the
--api-keycommand-line argument:bash node {baseDir}/bin/run.mjs --operation "search" --api-key "$JUST_SERP_API_KEY" --params-json '{"query":"<query>"}'The implementation requires the argument and inserts its value into the authentication header:
javascript if (!args.apiKey) { fail("Missing required --api-key argument."); } const params = parseParams(args.paramsJson); applyDefaults(operation, params); validateRequired(operation, params); const baseUrl = manifest.baseUrl; const url = new URL(operation.path, ensureBaseUrl(baseUrl)); applyPathParams(operation, params, url); applyQueryParams(operation, params, url); const requestInit = { headers: { "accept": "application/json", "X-API-Key": args.apiKey, }, method: operation.method, };The command-line parser stores the secret directly from the process argument vector:
javascript function parseArgs(argv) { const parsed = { apiKey: null, operation: null, paramsJson: "{}" }; for (let index = 0; index < argv.length; index += 1) { const flag = argv[index]; const value = argv[index + 1]; if (flag === "--operation") { parsed.operation = value; index += 1; continue; } if (flag === "--params-json") { parsed.paramsJson = value; index += 1; continue; } if (flag === "--api-key") { parsed.apiKey = value; index += 1; continue; }Technical Analysis
Although the documented command obtains the credential from the
JUST_SERP_API_KEYenvironment variable, the shell expands that variable before starting Node.js. The resulting plaintext A ...[truncated 2079 chars]- Remediation
View remediation
Remediation Suggestions
-
Read the credential directly from the process environment rather than requiring it as a command-line argument:
javascript const apiKey = process.env.JUST_SERP_API_KEY; if (!apiKey) { fail("Missing required JUST_SERP_API_KEY environment variable."); } -
Use
apiKeyonly when constructing the request header:javascript const requestInit = { headers: { accept: "application/json", "X-API-Key": apiKey, }, method: operation.method, }; -
Remove
--api-keyhandling fromparseArgsand updateSKILL.mdto use:bash JUST_SERP_API_KEY="$JUST_SERP_API_KEY" node {baseDir}/bin/run.mjs \ --operation "search" \ --params-json '{"query":"<query>"}'If the environment is already configured, omit the inline assignment entirely.
-
If an explicit alternative input mechanism is necessary, accept the secret through protected standard input or a permission-restricted credential file instead of the argument vector.
-
Ensure error messages, debug output, telemetry, and request logging redact
X-API-Keyand never serialize the credential. -
Rotate any API key that may previously have been exposed through command histories, process-monitoring systems, CI logs, orchestration metadata, or telemetry.
-
