T09 · Insecure Skill Coding Practices
- Location
alpha.js:29- Finding
Insecure API Key Exposure Through Command-Line Arguments, Output, Plaintext Storage, and Request URLs
- Content
View full analysis
Vulnerability Details
File Location:
SKILL.md:25-29;alpha.js:29-34;alpha.js:68;alpha.js:104;alpha.js:144;alpha.js:184;alpha.js:224;alpha.js:251;alpha.js:317-326
Vulnerability Type: Sensitive credential exposure and insecure secret storage
Risk Level: MediumVulnerable Code
SKILL.md:25-29documents passing the API key as a command-line argument:bash # Use your own API key node alpha.js apikey YOUR_API_KEYalpha.js:29-34stores the key in a plaintext JSON file without explicitly restrictive permissions:javascript // Save configuration function saveConfig() { fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2)); }alpha.js:317-326reads the secret directly from the command line, persists it, and prints the complete value:javascript case 'apikey': if (!args[1]) { console.error('Please provide an API key'); process.exit(1); } config.apiKey = args[1]; saveConfig(); console.log(`API key has been set to: ${args[1]}`); process.exit(0);The original source contains equivalent user-facing messages in Chinese. The security-relevant behavior is the direct use and disclosure of
args[1].The key is also embedded in request URLs at
alpha.js:68,104,144,184,224, and251:javascript const url = `https://www.alphavantage.co/query?function=GLOBAL_QUOTE&symbol=${symbol}&apikey=${config.apiKey}`;javascript const url = `https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol=${symbol}&outputsize=${outputSize}&apikey=${config.apiKey}`;javascript const url = `https://www.alphavantage.co/query?function=TIME_SERIES_WEEKLY&symbol=${symbol}&apikey=${config.apiKey}`;javascript const url = `https://www.alphavantage.co/query?function=TIME_SERIES_MONTHLY&symbol=${symbol}&apikey=${config.apiKey}`;j ...[truncated 2805 chars]- Remediation
View remediation
Remediation Suggestions
-
Do not accept secrets as ordinary command-line arguments.
- Prefer the existing
ALPHA_KEYenvironment-variable mechanism for noninteractive execution. - For interactive configuration, read the key from a masked prompt or standard input without echoing it.
- Update
SKILL.mdso it no longer recommendsnode alpha.js apikey YOUR_API_KEY.
- Prefer the existing
-
Never print the complete credential.
- Replace the current confirmation with a generic message such as
API key configured successfully. - If identification is necessary, display only a small masked suffix, such as
****1234.
- Replace the current confirmation with a generic message such as
-
Use secure credential storage.
- Prefer an operating-system credential manager or secret-management service.
- If local file storage remains necessary, create the file with owner-only permissions and verify permissions after creation:
javascript fs.writeFileSync( CONFIG_FILE, JSON.stringify(config, null, 2), { encoding: 'utf8', mode: 0o600 } ); fs.chmodSync(CONFIG_FILE, 0o600);- Ensure
config.jsonis excluded from version control, backups, support bundles, and artifact packaging where appropriate.
-
Minimize URL-based credential exposure.
- Avoid logging complete request URLs.
- Redact
apikeyvalues in diagnostics, telemetry, proxy logs, and exception reports. - If the upstream API supports a credential header, use that mechanism instead of a query parameter. If Alpha Vantage requires a query parameter, constrain logging and instrumentation accordingly.
-
Rotate exposed keys.
- Any key previously supplied through the documented CLI command, printed to logs, or stored with permissive access should be treated as potentially disclosed and replaced.
-
