Preflight Checklist
Problem Statement
Claude Code can access secrets through multiple vectors that existing mitigations don't cover:
File reads - .claudeignore and permission hooks are bypassed via system reminders (#8031) and indexing (#4160). In one case Claude read .env.local and committed the values to an env.example file that was pushed to git (#7921).
Shell environment - env, printenv, or echo $VAR exposes any exported variable regardless of file protections. Even when using external secret managers (1Password CLI, HashiCorp Vault, AWS SSM etc.) to keep secrets off disk, once values are resolved into the shell environment they're fully visible.
Aggressive debugging - Claude hunts for credentials when troubleshooting auth errors and injects them into curl commands (#9637).
Current workarounds like .claudeignore, permission hooks, and per-command wrapping with op run are either incomplete (only covering file access, not shell environment) or too restrictive (limiting Claude's ability to help with debugging).
Proposed Solution
A single sensitive config in .claude/settings.json that lets users mark env var names and file paths as sensitive. Claude sees they exist but never sees the values/contents.
{
"sensitive": {
"envPatterns": ["*_TOKEN", "*_KEY", "*_SECRET", "*_PASSWORD", "*_API_*"],
"paths": [".env.local", ".env.production", "secrets/", "*.pem", "*.key"]
}
}
Env var behaviour - when Claude encounters a matching variable via shell output, file read, or system reminder:
STRIPE_SECRET=*****
DATABASE_URL=*****
NODE_ENV=development // not matched, visible as normal
File/directory behaviour - matched paths are fully blocked from context injection. Unlike .claudeignore (which only prevents indexing), this filter applies to all access vectors including system reminders, indirect reads, and command output like cat .env.local. Claude sees the file/directory exists (so it can reference it in scripts or configs) but never sees the contents.
The filter applies at the context injection boundary - glob match on variable names and file paths, redact/block before anything enters Claude's context. No secret detection heuristics, no proxy architecture, no specific tool integrations required.
Alternative Solutions
Priority
High - Significant impact on productivity
Feature Category
Configuration and settings
Use Case Example
- I'm working on a Node.js app that uses Stripe, a database, and various third-party APIs
- My
.env.local has raw credentials; my .zshrc exports API keys via op read
- I ask Claude Code to debug a failing API call
- Claude runs
env | grep STRIPE or cat .env.local to find credentials and stuffs them into a curl command - now my secrets are in Claude's context
- With this feature, I'd add
"sensitive": { "envPatterns": ["*_KEY", "*_SECRET", "*_TOKEN"], "paths": [".env.local", "*.pem"] } to my .claude/settings.json
- Claude would see
STRIPE_SECRET=***** and know the variable is configured without ever seeing the value
- Claude could still help debug by checking the variable exists, verifying the format of non-sensitive config, and suggesting fixes - just without accessing the actual secret
Additional Context
Related issues showing this is a recurring problem:
This proposal consolidates these into one focused, minimal solution: glob patterns on var names and file paths, filtered at the context boundary. Tool-agnostic, composable with existing workarounds, and simple enough to ship without major architectural changes.
Preflight Checklist
Problem Statement
Claude Code can access secrets through multiple vectors that existing mitigations don't cover:
File reads -
.claudeignoreand permission hooks are bypassed via system reminders (#8031) and indexing (#4160). In one case Claude read.env.localand committed the values to anenv.examplefile that was pushed to git (#7921).Shell environment -
env,printenv, orecho $VARexposes any exported variable regardless of file protections. Even when using external secret managers (1Password CLI, HashiCorp Vault, AWS SSM etc.) to keep secrets off disk, once values are resolved into the shell environment they're fully visible.Aggressive debugging - Claude hunts for credentials when troubleshooting auth errors and injects them into curl commands (#9637).
Current workarounds like
.claudeignore, permission hooks, and per-command wrapping withop runare either incomplete (only covering file access, not shell environment) or too restrictive (limiting Claude's ability to help with debugging).Proposed Solution
A single
sensitiveconfig in.claude/settings.jsonthat lets users mark env var names and file paths as sensitive. Claude sees they exist but never sees the values/contents.{ "sensitive": { "envPatterns": ["*_TOKEN", "*_KEY", "*_SECRET", "*_PASSWORD", "*_API_*"], "paths": [".env.local", ".env.production", "secrets/", "*.pem", "*.key"] } }Env var behaviour - when Claude encounters a matching variable via shell output, file read, or system reminder:
File/directory behaviour - matched paths are fully blocked from context injection. Unlike
.claudeignore(which only prevents indexing), this filter applies to all access vectors including system reminders, indirect reads, and command output likecat .env.local. Claude sees the file/directory exists (so it can reference it in scripts or configs) but never sees the contents.The filter applies at the context injection boundary - glob match on variable names and file paths, redact/block before anything enters Claude's context. No secret detection heuristics, no proxy architecture, no specific tool integrations required.
Alternative Solutions
.claudeignore- only prevents indexing, bypassed via system reminders ([BUG] Claude Code could read the .env content even .claude/settings.json is configured #8031) and indirect access (Support ".claudeignore" file to prevent secret exposure #4160)op runper-command - secrets only exist in child process, but this limits Claude to running individual wrapped commands rather than freely debuggingPriority
High - Significant impact on productivity
Feature Category
Configuration and settings
Use Case Example
.env.localhas raw credentials; my.zshrcexports API keys viaop readenv | grep STRIPEorcat .env.localto find credentials and stuffs them into a curl command - now my secrets are in Claude's context"sensitive": { "envPatterns": ["*_KEY", "*_SECRET", "*_TOKEN"], "paths": [".env.local", "*.pem"] }to my.claude/settings.jsonSTRIPE_SECRET=*****and know the variable is configured without ever seeing the valueAdditional Context
Related issues showing this is a recurring problem:
.claudeignoreinsufficient - Claude finds indirect access routes.claudeignorefor env files requestThis proposal consolidates these into one focused, minimal solution: glob patterns on var names and file paths, filtered at the context boundary. Tool-agnostic, composable with existing workarounds, and simple enough to ship without major architectural changes.