T09 · Insecure Skill Coding Practices
Error
- Location
- manage.md:5
- Finding
- API Keys Exposed Through Command-Line Arguments and Plaintext Verification Output<![CDATA[ ## Vulnerability Details **File Location**: `manage.md`, lines 5-7, 14-17, and 40-49 **Vulnerability Type**: Plaintext credential exposure **Risk Level**: High ### Vulnerable Code `manage.md:5-7`: ```bash ### macOS ```bash security add-generic-password -s "keys:SERVICE" -a "$USER" -w "THE-API-KEY" ``` `manage.md:14-17`: ```bash ### macOS ```bash security delete-generic-password -s "keys:SERVICE" -a "$USER" security add-generic-password -s "keys:SERVICE" -a "$USER" -w "NEW-API-KEY" ``` `manage.md:40-49`: ```bash ## Verify a Key Exists ```bash # This should return the key (or error if not found) # macOS security find-generic-password -s "keys:SERVICE" -a "$USER" -w # Linux secret-tool lookup service keys:SERVICE ``` ``` ### Technical Analysis The macOS add and update instructions place the API key directly in a command-line argument through `-w "THE-API-KEY"` and `-w "NEW-API-KEY"`. When users replace these placeholders with real credentials, the secret can be retained in shell history and may be exposed through process inspection or terminal-session logging. The verification instructions explicitly retrieve and print the decrypted credential to standard output. On macOS, `security find-generic-password ... -w` prints the password, while on Linux, `secret-tool lookup` prints the stored secret. If these commands are run through an AI Agent terminal or another captured execution environment, the key may enter Agent context, command transcripts, application logs, or tool output. This behavior contradicts the Skill's stated security property that keys are never exposed to Agent context. Although `keys-broker.sh` itself does not return stored keys directly, the documented management workflow provides commands that do. ### Attack Path 1. A user follows the documented macOS key-addition or rotation instructions. 2. The user replaces `THE-API-KEY` or `NEW-API-KEY` with an actual credential. 3. The complete command, including the plaintext creden ...[truncated 1419 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. **Do not pass credentials as command-line arguments.** Replace the macOS examples with an interactive workflow that allows the `security` utility to prompt for the secret rather than embedding it in the command. 2. **Do not print decrypted credentials during verification.** Verification should report only whether a credential exists. Suppress secret output and inspect the command's exit status, for example: ```bash if security find-generic-password -s "keys:SERVICE" -a "$USER" -w >/dev/null 2>&1; then echo "Key exists" else echo "Key not found" fi ``` For Linux: ```bash if secret-tool lookup service keys:SERVICE >/dev/null 2>&1; then echo "Key exists" else echo "Key not found" fi ``` 3. **Keep Linux secret entry interactive.** Continue using `secret-tool store`, which prompts for the secret, and warn users not to pipe credentials from shell command lines or store them in environment variables. 4. **Add explicit Agent-safety guidance.** State that an Agent must never execute commands that return decrypted credentials and must not request that users place keys in command arguments, chat messages, or Agent-controlled terminals. 5. **Address existing exposure.** Users who followed the vulnerable instructions should remove affected commands from shell history and terminal logs, rotate the potentially exposed credentials, revoke old keys, and review provider audit logs for unauthorized use. 6. **Apply least privilege at the provider.** Restrict each API key to the minimum required scopes, projects, repositories, source addresses, spending limits, and expiration period so that accidental disclosure has reduced impact. ]]>
