Skip to content

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

Description

@patons02

Preflight Checklist

  • I have searched existing requests and this feature hasn't been requested yet
  • 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

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:

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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions