Handle Secrets
Best practices for handling secrets that users pass to your CLI tool (API keys, tokens, passwords), not secrets used during development.
Core Principles
- Never accept secrets as command-line arguments - Arguments are visible via
ps aux, recorded in shell history, and captured by audit logs
- Make the secure path the default - Users who do nothing special should get the safest behavior
- Separate config from credentials - Non-sensitive settings and secret material belong in different files
- Mask secrets in all output - Debug logs, error messages, HTTP traces, and verbose output must redact secret values
- Warn loudly about insecure behavior - If users opt into something dangerous, tell them explicitly
Security Hierarchy (Safest to Most Dangerous)
| Method |
Safety |
Use when |
| OS keychain / credential helper |
Safest |
Persistent storage for interactive users |
Secret references (op://, vault URIs) |
Safe |
Storing pointers instead of secrets |
| Stdin / pipes / file descriptors |
Safe |
Automation and scripting |
| Interactive TTY prompt |
Safe |
Human users at a terminal |
| Config files (0600 permissions) |
Acceptable |
Persistent storage without keychain |
| Environment variables |
Acceptable |
CI/CD pipelines and containers |
| Command-line arguments |
Never |
- |
Workflow
- Quick reviews: Check against
references/checklist.md
- Choosing an input method: Read
references/security-hierarchy.md
- Designing credential flows: Read
references/design-patterns.md
- Avoiding known pitfalls: Read
references/anti-patterns.md
- Language-specific code: Read
references/language-libraries.md
Reference Navigation
Quick reviews (default):
references/checklist.md - Condensed, actionable rules
Deep dives by topic:
references/security-hierarchy.md - Ranked input methods with attack surfaces and mitigations
references/design-patterns.md - Credential fallback chains, OAuth device flow, token hygiene, masking
references/anti-patterns.md - Real CVEs and incidents from insecure secret handling
references/language-libraries.md - Rust, Go, Python, Node.js, Ruby libraries and code patterns
Credential Resolution Fallback Chain
Tools should resolve credentials in this order:
- Environment variable (for CI/CD)
- Credential helper / OS keychain (for persistent storage)
- Config file with 0600 permissions (fallback)
- Interactive TTY prompt (for humans)
Never fall through to accepting --password <value> as an argument.
Sources
Converted and distributed by TomeVault — claim your Tome and manage your conversions.
1---2name: cboone-cboone-cc-plugins-handle-secrets3description: Handle Secrets4---56# Handle Secrets78Best practices for handling secrets that **users pass to your CLI tool** (API keys, tokens, passwords), not secrets used during development.910## Core Principles11121. **Never accept secrets as command-line arguments** - Arguments are visible via `ps aux`, recorded in shell history, and captured by audit logs131. **Make the secure path the default** - Users who do nothing special should get the safest behavior141. **Separate config from credentials** - Non-sensitive settings and secret material belong in different files151. **Mask secrets in all output** - Debug logs, error messages, HTTP traces, and verbose output must redact secret values161. **Warn loudly about insecure behavior** - If users opt into something dangerous, tell them explicitly1718## Security Hierarchy (Safest to Most Dangerous)1920| Method | Safety | Use when |21| --------------------------------------- | ---------- | ---------------------------------------- |22| OS keychain / credential helper | Safest | Persistent storage for interactive users |23| Secret references (`op://`, vault URIs) | Safe | Storing pointers instead of secrets |24| Stdin / pipes / file descriptors | Safe | Automation and scripting |25| Interactive TTY prompt | Safe | Human users at a terminal |26| Config files (0600 permissions) | Acceptable | Persistent storage without keychain |27| Environment variables | Acceptable | CI/CD pipelines and containers |28| Command-line arguments | **Never** | - |2930## Workflow31321. **Quick reviews:** Check against `references/checklist.md`331. **Choosing an input method:** Read `references/security-hierarchy.md`341. **Designing credential flows:** Read `references/design-patterns.md`351. **Avoiding known pitfalls:** Read `references/anti-patterns.md`361. **Language-specific code:** Read `references/language-libraries.md`3738## Reference Navigation3940**Quick reviews (default):**4142- `references/checklist.md` - Condensed, actionable rules4344**Deep dives by topic:**4546- `references/security-hierarchy.md` - Ranked input methods with attack surfaces and mitigations47- `references/design-patterns.md` - Credential fallback chains, OAuth device flow, token hygiene, masking48- `references/anti-patterns.md` - Real CVEs and incidents from insecure secret handling49- `references/language-libraries.md` - Rust, Go, Python, Node.js, Ruby libraries and code patterns5051## Credential Resolution Fallback Chain5253Tools should resolve credentials in this order:54551. Environment variable (for CI/CD)561. Credential helper / OS keychain (for persistent storage)571. Config file with 0600 permissions (fallback)581. Interactive TTY prompt (for humans)5960Never fall through to accepting `--password <value>` as an argument.6162## Sources6364- [Building CLI tools that handle user secrets responsibly](https://www.macchaffee.com/blog/2025/cli-secret-handling/) - Mac Chaffee65- GitHub CLI, Docker, AWS CLI, kubectl, and 1Password CLI implementations6667---68> Converted and distributed by [TomeVault](https://tomevault.io/claim/cboone) — claim your Tome and manage your conversions.69<!-- tomevault:4.0:skill_md:2026-04-13 -->