C.W.K.
Stream
Lesson 03 of 05 · published

The Defense — Make Secrets Unreadable, Not 'Private'

~15 min · defense, keychain, ignore-files

Level 0Greenhorn
0 XP0/53 lessons0/14 achievements
0/100 XP to next level100 XP to go0% complete

The only reliable defense is to never let the LLM see the secret in the first place. "Tell it not to share" is not a defense.

The layered strategy

LayerWhat it doesHow
1. Don't put secrets in files the agent readsIf it's not in context, it can't be repeatedUse OS keychain, secrets manager, or runtime env vars from outside the repo
2. Ignore-filesBelt-and-suspenders for #1.cursorignore, .aiignore, .aiderignore, etc.
3. Use placeholders in committed configsReal values exist only in the running process.env.example with API_KEY=<FROM_KEYCHAIN>
4. Rotate aggressivelyLimits blast radius if leakedOPENAI / Anthropic / GitHub keys: rotate quarterly minimum
5. Scoped tokensEven leaked tokens have small blast radiusRead-only DB users, repo-scoped GitHub PATs

Code

.cursorignore (and equivalents) — what to always list·text
# .cursorignore (and equivalents)
.env
.env.*
*.pem
*.key
*.crt
*.p12
secrets/
credentials/
config/secrets.*
*.sqlite          # may contain session tokens, password hashes
*.db
.ssh/
.aws/credentials
.gnupg/
The keychain pattern — fetch secrets at runtime·python
import keyring  # pip install keyring  -- backed by macOS Keychain / Windows Credential Vault / Secret Service

def get_api_key() -> str:
    key = keyring.get_password("my-app", "OPENAI_API_KEY")
    if not key:
        raise RuntimeError("Set with: keyring set my-app OPENAI_API_KEY")
    return key

# In committed code, only this function exists.
# The actual key was set once via CLI: keyring set my-app OPENAI_API_KEY
What goes in .env.example (and gets committed)·text
# Committed file. Real values come from keychain/keyring at runtime.
OPENAI_API_KEY=<set with: keyring set my-app OPENAI_API_KEY>
ANTHROPIC_API_KEY=<set with: keyring set my-app ANTHROPIC_API_KEY>
DB_PASSWORD=<set with: keyring set my-app DB_PASSWORD>

External links

Exercise

On one of your projects today: (1) install keyring (pip install keyring); (2) keyring set <app> OPENAI_API_KEY for any keys currently in .env; (3) replace .env reads with a get_secret() helper that calls keyring; (4) replace .env values with <FROM_KEYCHAIN> placeholders; (5) add .env.* to your .cursorignore. The agent now sees structure, not secrets.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.