T09 · Insecure Skill Coding Practices
Warning
- Location
- tools/websearchapi/websearchapi.js:37
- Finding
- SearchAPI Credential Exposed Through Command-Line Arguments, Plaintext Storage, and URL Query Parameters## Vulnerability Details **File Locations**: - `SKILL.md:28-31` - `tools/websearchapi/websearchapi.js:37-40` - `tools/websearchapi/websearchapi.js:78-85` - `tools/websearchapi/websearchapi.js:124-126` **Vulnerability Type**: Insecure credential handling **Risk Level**: Medium ### Vulnerable 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_KEY ``` The 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: 1. Supplying the key as `config set-key YOUR_API_KEY` can 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. 2. `fs.writeFileSync` stores the complete credential in `config.json` as plaintext. No explicit `0600` mode is requested, so effective permissions depend on the process umask and any permissions already present on the file. 3. The key is included in the HT ...[truncated 2025 chars]
- Remediation
- ## Remediation Suggestions 1. **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.md` and `README.md` so examples do not encourage placing credentials in shell history. 2. **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.json` to `.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. 3. **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_key` from errors, tracing, telemetry, and proxy logs. - Review SearchAPI's official authentication guidance before changing the request format. 4. **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.
