T09 · Insecure Skill Coding Practices
- Location
tools/websearchapi/websearchapi.js:37- Finding
SearchAPI Credential Exposed Through Command-Line Arguments, Plaintext Storage, and URL Query Parameters
- Content
View full analysis
Vulnerability Details
File Locations:
SKILL.md:28-31tools/websearchapi/websearchapi.js:37-40tools/websearchapi/websearchapi.js:78-85tools/websearchapi/websearchapi.js:124-126
Vulnerability Type: Insecure credential handling
Risk Level: MediumVulnerable Code
The documented configuration procedure places the API key directly in a command-line argument:
bash # Copy tools/websearchapi to your project # Configure API Key (required) cd tools/websearchapi node websearchapi.js config set-key YOUR_API_KEYThe key is saved as part of an unencrypted JSON configuration file without explicitly restrictive file permissions:
javascript function saveConfig(config) { fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2)); console.log('✅ 配置已保存到:', CONFIG_FILE); }The saved key is subsequently inserted into the request parameters:
javascript const params = { q: query, num: options.num || config.num, hl: options.lang || config.lang, gl: options.gl || config.gl, engine: engine, api_key: config.apiKey };Those parameters, including the credential, are serialized into the request URL:
javascript function executeSearch(params, timeout) { return new Promise((resolve, reject) => { const url = `${API_BASE}?${querystring.stringify(params)}`;Technical Analysis
The API credential is exposed through three related channels:
- Supplying the key as
config set-key YOUR_API_KEYcan retain it in shell history. Depending on operating-system access controls, command-line arguments may also be visible to other local processes while the command runs. fs.writeFileSyncstores the complete credential inconfig.jsonas plaintext. No explicit0600mode is requested, so effective permissions depend on the process umask and any permissions already present on the file.- The key is included in the HT ...[truncated 2025 chars]
- Remediation
View remediation
Remediation Suggestions
-
Avoid command-line key submission
- Prefer a protected environment variable such as
SEARCHAPI_API_KEY. - If persistent configuration is necessary, read the key from an interactive hidden prompt or standard input rather than a positional argument.
- Update
SKILL.mdandREADME.mdso examples do not encourage placing credentials in shell history.
- Prefer a protected environment variable such as
-
Protect persistent configuration
- Create the configuration file with owner-only permissions:
javascript fs.writeFileSync( CONFIG_FILE, JSON.stringify(config, null, 2), { mode: 0o600 } ); fs.chmodSync(CONFIG_FILE, 0o600); - Store secrets separately from non-sensitive defaults.
- Add
config.jsonto.gitignore, package exclusion rules, backup exclusions where appropriate, and deployment secret-scanning policies. - Consider using the operating system's credential store or a managed secret service instead of a plaintext file.
- Create the configuration file with owner-only permissions:
-
Reduce credential exposure in requests
- If SearchAPI supports an authorization header, transmit the key in that header instead of the URL.
- If the provider mandates a query parameter, ensure request URLs are never logged and redact
api_keyfrom errors, tracing, telemetry, and proxy logs. - Review SearchAPI's official authentication guidance before changing the request format.
-
Handle existing exposure
- Rotate any key previously configured through this mechanism.
- Remove affected shell-history entries and URL-bearing logs where operationally possible.
- Audit API usage for unexpected requests and configure quota or billing alerts.
-
