T09 · Insecure Skill Coding Practices
- Location
bin/run.mjs:182- Finding
API Key Exposed Through Command-Line Arguments
- Content
View full analysis
Vulnerability Details
File Location:
bin/run.mjs:113-114, 129, 182-198; documented usage inSKILL.md:46, 54
Vulnerability Type: Sensitive credential exposure through process arguments
Risk Level: MediumVulnerable Code
js if (!args.apiKey) { fail("Missing required --api-key argument."); }js const requestInit = { headers: { "accept": "application/json", "X-API-Key": args.apiKey, }, method: operation.method, };js 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 === "--api-key") { parsed.apiKey = value; index += 1; continue; } fail(`Unknown argument "${flag}".`); } return parsed; }The corresponding documented invocation is:
bash node {baseDir}/bin/run.mjs --operation "lens" --api-key "$JUST_SERP_API_KEY" --params-json '{"url":"<url>"}'Technical Analysis
The helper requires the API key to be supplied using the
--api-keycommand-line option. Although the shell expression references an environment variable, the shell expands that variable before starting Node.js. The resulting plaintext key is therefore placed in the process argument vector.Process arguments may be visible to other local users, privileged monitoring agents, process inspection utilities, audit systems, diagnostic collectors, or command-line telemetry, depending on the operating system and deployment configuration. The documentation's warning not to paste or log the key does not prevent this exposure because the prescribed invocation itself transfers the secret into process arguments.
The key is legitimately sent to the fixed HTTPS API endpoint in the
X-API-Keyheader; that behavior is not itself th ...[truncated 1257 chars]- Remediation
View remediation
Remediation Suggestions
-
Read the credential directly from the environment rather than accepting it as a command-line argument:
js const apiKey = process.env.JUST_SERP_API_KEY; if (!apiKey) { fail("Missing required JUST_SERP_API_KEY environment variable."); } -
Use the environment-derived value only when constructing the authentication header:
js const requestInit = { headers: { accept: "application/json", "X-API-Key": apiKey, }, method: operation.method, }; -
Remove
--api-keyhandling fromparseArgsso users cannot accidentally place credentials in the process argument vector. -
Update
SKILL.mdto document invocation without a credential argument:bash JUST_SERP_API_KEY="$JUST_SERP_API_KEY" \ node {baseDir}/bin/run.mjs \ --operation "lens" \ --params-json '{"url":"<url>"}'If the environment variable is already exported, omit the inline assignment entirely.
-
For higher-assurance environments, retrieve the key from a dedicated secret manager or protected file descriptor and ensure that errors, debug logs, and telemetry never serialize authentication headers or secret values.
-
Rotate the existing API key if the documented command has been used in an environment where process arguments or command-line telemetry may have been accessible to unauthorized parties.
-
