[FEATURE] Mark sensitive environment variables and file paths to prevent secret exposure

Resolved 💬 6 comments Opened Feb 11, 2026 by patons02 Closed Mar 24, 2026

Preflight Checklist

  • [x] I have searched existing requests and this feature hasn't been requested yet
  • [x] This is a single feature request (not multiple features)

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

  • .claudeignore - only prevents indexing, bypassed via system reminders (#8031) and indirect access (#4160)
  • Permission hooks - can deny file reads but don't cover shell environment access, and Claude can still see file contents via system reminders
  • op run per-command - secrets only exist in child process, but this limits Claude to running individual wrapped commands rather than freely debugging
  • Not exporting secrets - breaks tooling that depends on env vars
  • #2695 proposed a "Zero-Trust Architecture" with pattern-based secret detection, placeholder replacement, local execution proxies, and encrypted stores - far more complex than needed

Priority

High - Significant impact on productivity

Feature Category

Configuration and settings

Use Case Example

  1. I'm working on a Node.js app that uses Stripe, a database, and various third-party APIs
  2. My .env.local has raw credentials; my .zshrc exports API keys via op read
  3. I ask Claude Code to debug a failing API call
  4. 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
  5. With this feature, I'd add "sensitive": { "envPatterns": ["*_KEY", "*_SECRET", "*_TOKEN"], "paths": [".env.local", "*.pem"] } to my .claude/settings.json
  6. Claude would see STRIPE_SECRET=***** and know the variable is configured without ever seeing the value
  7. 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:

  • #2695 - Zero-trust env var architecture (open, 9 upvotes, proposes a more complex version of this)
  • #9637 - Claude aggressively reads secrets from .env files
  • #7921 - Claude committed .env.local secrets to git via env.example
  • #8031 - System reminders bypass .env read permissions
  • #4160 - .claudeignore insufficient - Claude finds indirect access routes
  • #2637 - Original .claudeignore for env files request
  • #112 - .env file access security risk
  • #401 - Automatic .env loading into bash environment

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.

View original on GitHub ↗

This issue has 6 comments on GitHub. Read the full discussion on GitHub ↗