Secure Keys
Audit and harden how the user's AI tools authenticate with external services. Run the phases in order. Read first; change only after showing a plan and getting a yes.
Absolute rules: never violate
- Never print, echo, log, or display a secret value. Refer to a key only by name and location, e.g.
OPENAI_API_KEY in .env:3. When showing matches, redact the value to a prefix like sk-….
- Never ask the user to paste a key into the conversation. If a value must be entered, give them a command to run that reads it off-screen (their shell, a tool prompt), and have the tool store it directly.
- Destructive steps require explicit confirmation first: rotating, revoking, deleting a key, or rewriting git history. State the blast radius before doing any of them.
- Discovery is read-only. Migrate one credential at a time and verify it live before moving on. Never batch-and-pray.
Phase 1: Discover (read-only)
Find credentials and report location + type only, never the value:
- Files:
.env*, and config like .mcp.json, **/claude_desktop_config.json, .cursor/, .vscode/, plus *.json|*.yaml|*.toml holding key-shaped values.
- Source: grep for key shapes:
sk-, sk-ant-, AIza, ghp_/gho_, xox, AWS AKIA, generic Bearer tokens.
- History:
~/.zsh_history and ~/.bash_history, current env vars, and git log -p / git grep across history for committed or pushed secrets.
Output a table: name · location · type (LLM key / connected-account token / cloud cred / signing key) · exposed? (committed, pushed, or in shell history = yes).
Phase 2: Classify
Split findings into:
- (a) Could use a login instead: a "Sign in with Google/GitHub/…" OAuth flow or a managed connector exists. List the migration path for each. Prefer this; a revocable, scoped login beats a long-lived key.
- (b) Must stay a key: model API keys, signing keys, tokens with no OAuth path. These go to secure storage in Phase 4.
Phase 3: Triage exposure
Anything in committed files, pushed history, or shell history is compromised. Mark it rotate, top priority. Order by blast radius: account-access tokens (email, drive, repo, cloud) before spend-only model keys, because money is cappable and access is not.
Phase 4: Recommend storage (name the tradeoff)
For each must-keep key, recommend a home and say plainly who ends up holding it:
- macOS Keychain (
security): local, free, does not sync. Best default for single-machine dev keys.
- Cloud secrets manager (1Password
op run, Bitwarden, AWS Parameter Store, GCP Secret Manager, Doppler, Infisical): syncs across devices, survives a dead laptop, trusts a vendor; the key still reaches the machine at use.
- Cloudflare AI Gateway (BYOK), LLM provider keys only: the real key never touches the machine, the user carries a gateway token instead. Free.
Recommend by the user's actual setup. Ask which they want; never assume.
Phase 5: Migrate (one at a time, verified)
Store the key in the chosen vault, then rewrite each app, script, or MCP server to fetch it at runtime (security find-generic-password, op run --, or the gateway endpoint) so config holds only a pointer. Run the tool once to confirm it still works.
Phase 6: Harden
For each key, apply the smallest practical scope, a spend cap, an expiry, and an IP allowlist where the provider supports them. Then walk the user through revoking and reissuing every rotate key from Phase 3.
Phase 7: Verify
Re-run Phase 1 and confirm zero plaintext keys remain in code, configs, .env, env vars, and shell history. Report what changed, what was rotated, and anything still exposed and why, without ever showing a value.
1---2name: secure-keys3description: Audit and lock down how AI tools hold API keys and credentials. Finds exposed keys across code, config files, .env files, environment variables, shell history, and git history; moves connections to OAuth / "Sign in with X" where one exists; migrates the rest into secure storage (macOS Keychain, a cloud secrets manager, or Cloudflare AI Gateway) with runtime retrieval instead of files; flags what to rotate; and tightens scope, spend caps, expiry, and IP rules. Trigger on "secure my keys", "audit my credentials/secrets", "find exposed API keys", "lock down my secrets", "key hygiene", "did I leak a key", or after wiring up an MCP server or a new integration.4---56# Secure Keys78Audit and harden how the user's AI tools authenticate with external services. Run the phases in order. Read first; change only after showing a plan and getting a yes.910## Absolute rules: never violate1112- **Never print, echo, log, or display a secret value.** Refer to a key only by name and location, e.g. `OPENAI_API_KEY in .env:3`. When showing matches, redact the value to a prefix like `sk-…`.13- **Never ask the user to paste a key into the conversation.** If a value must be entered, give them a command to run that reads it off-screen (their shell, a tool prompt), and have the tool store it directly.14- **Destructive steps require explicit confirmation first**: rotating, revoking, deleting a key, or rewriting git history. State the blast radius before doing any of them.15- **Discovery is read-only.** Migrate one credential at a time and verify it live before moving on. Never batch-and-pray.1617## Phase 1: Discover (read-only)1819Find credentials and report **location + type only, never the value**:20- Files: `.env*`, and config like `.mcp.json`, `**/claude_desktop_config.json`, `.cursor/`, `.vscode/`, plus `*.json|*.yaml|*.toml` holding key-shaped values.21- Source: grep for key shapes: `sk-`, `sk-ant-`, `AIza`, `ghp_`/`gho_`, `xox`, AWS `AKIA`, generic `Bearer ` tokens.22- History: `~/.zsh_history` and `~/.bash_history`, current env vars, and `git log -p` / `git grep` across history for committed or pushed secrets.2324Output a table: **name · location · type** (LLM key / connected-account token / cloud cred / signing key) · **exposed?** (committed, pushed, or in shell history = yes).2526## Phase 2: Classify2728Split findings into:29- **(a) Could use a login instead**: a "Sign in with Google/GitHub/…" OAuth flow or a managed connector exists. List the migration path for each. Prefer this; a revocable, scoped login beats a long-lived key.30- **(b) Must stay a key**: model API keys, signing keys, tokens with no OAuth path. These go to secure storage in Phase 4.3132## Phase 3: Triage exposure3334Anything in committed files, pushed history, or shell history is compromised. Mark it **rotate**, top priority. Order by blast radius: account-access tokens (email, drive, repo, cloud) before spend-only model keys, because money is cappable and access is not.3536## Phase 4: Recommend storage (name the tradeoff)3738For each must-keep key, recommend a home and say plainly **who ends up holding it**:39- **macOS Keychain** (`security`): local, free, does not sync. Best default for single-machine dev keys.40- **Cloud secrets manager** (1Password `op run`, Bitwarden, AWS Parameter Store, GCP Secret Manager, Doppler, Infisical): syncs across devices, survives a dead laptop, trusts a vendor; the key still reaches the machine at use.41- **Cloudflare AI Gateway (BYOK)**, LLM provider keys only: the real key never touches the machine, the user carries a gateway token instead. Free.4243Recommend by the user's actual setup. Ask which they want; never assume.4445## Phase 5: Migrate (one at a time, verified)4647Store the key in the chosen vault, then rewrite each app, script, or MCP server to **fetch it at runtime** (`security find-generic-password`, `op run --`, or the gateway endpoint) so config holds only a pointer. Run the tool once to confirm it still works.4849## Phase 6: Harden5051For each key, apply the smallest practical scope, a spend cap, an expiry, and an IP allowlist where the provider supports them. Then walk the user through revoking and reissuing every **rotate** key from Phase 3.5253## Phase 7: Verify5455Re-run Phase 1 and confirm zero plaintext keys remain in code, configs, `.env`, env vars, and shell history. Report what changed, what was rotated, and anything still exposed and why, without ever showing a value.