T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/qutedance-quotes.js:25
- Finding
- Plaintext API Key Storage in Tracked Configuration Is Encouraged and Prioritized## Vulnerability Details **File Location**: `scripts/qutedance-quotes.js:25-28`; related documentation at `SKILL.md:20-22` and configuration field at `config.json:3` **Vulnerability Type**: Plaintext secret storage and insecure credential precedence **Risk Level**: Medium ### Vulnerable Code ```js const API_KEY = CONFIG.apiKey || process.env.QUTEDANCE_API_KEY || ''; ``` Related documented configuration: ```json { "serviceUrl": "https://quotedance.api.gapgap.cc", "apiKey": "" } ``` The documentation explicitly directs users to place the API key in the configuration file for convenience. The distributed configuration currently contains an empty value, so no active credential was exposed in the audited artifact. ### Technical Analysis The implementation reads `apiKey` from the repository-local `config.json` before checking the `QUTEDANCE_API_KEY` environment variable. This design encourages users to save a live credential as plaintext inside the Skill directory and makes the less secure source take precedence over the safer environment-based mechanism. A populated configuration file can subsequently be committed to source control, included in backups or archives, copied with the workspace, or disclosed when the Skill directory is shared. The script then transmits the key in the `X-API-Key` header over HTTPS to the declared Qutedance service. That network transmission is necessary for the documented authentication flow and is not, by itself, covert exfiltration; the security issue is the credential's persistent plaintext storage. ### Attack Path 1. A user follows the documentation and writes a valid Qutedance API key into `config.json`. 2. The plaintext configuration is committed, archived, backed up, or shared with the Skill directory. 3. An unauthorized party obtains read access to that copy and extracts the API key. 4. The party submits the stolen key in an `X-API-Key` header to the configure ...[truncated 890 chars]
- Remediation
- ## Remediation Suggestions 1. Remove support for credentials stored in tracked `config.json`, or reserve that file exclusively for non-sensitive settings. 2. Read the key from `QUTEDANCE_API_KEY` or a platform-managed secret store: ```js const API_KEY = process.env.QUTEDANCE_API_KEY || ''; ``` 3. Update `SKILL.md` to instruct users never to place credentials in repository files. 4. If file-based secrets are operationally necessary, use a separate untracked file with restrictive filesystem permissions and add it to `.gitignore`. 5. Provide only a redacted example configuration, such as `config.example.json`, without an `apiKey` value. 6. Fail with a clear message when authentication is required but no key is available; never print the key in errors or logs. 7. Scan repository history and distributed archives for previously committed keys. Revoke and rotate any credential that may have been exposed. 8. Retain HTTPS certificate verification and restrict the service URL to approved HTTPS origins where deployment requirements permit.
