[FEATURE] Environment Variable Redaction for Hook Security
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 hooks execute with the user's full environment, including sensitive environment variables like API keys, tokens, and credentials. There's currently no built-in mechanism to prevent hooks from accidentally logging or exposing these secrets.
Risks include:
- Accidental logging: A hook that logs its environment for debugging may expose secrets
- Error messages: Stack traces or error output may include environment variable values
- Third-party hooks: Plugins or shared hooks may not be security-conscious
- Debug mode output:
claude --debugmay expose environment details - Transcript logging: Hook output recorded in transcripts could contain secrets
While Claude Code's security documentation mentions being careful with hooks, there's no automated protection.
Proposed Solution
Add an environmentVariableRedaction setting that automatically redacts sensitive environment variables from hook output.
Configuration
In settings.json:
{
"environmentVariableRedaction": {
"enabled": true,
"patterns": [
".*_KEY$",
".*_TOKEN$",
".*_SECRET$",
".*_PASSWORD$",
".*_CREDENTIAL.*"
],
"additionalVariables": [
"AWS_ACCESS_KEY_ID",
"AWS_SECRET_ACCESS_KEY",
"ANTHROPIC_API_KEY",
"GITHUB_TOKEN",
"DATABASE_URL"
],
"redactionString": "[REDACTED]"
}
}
Behavior
When enabled:
- Hook stdout/stderr filtering: Before displaying or logging hook output, scan for and redact values of sensitive environment variables
- Error message filtering: Redact secrets from error messages and stack traces
- Debug output filtering: Redact secrets from
--debugoutput - Transcript filtering: Redact secrets before writing to transcript files
Default Patterns
Out of the box, redact variables matching common patterns:
| Pattern | Examples |
|---------|----------|
| .*_KEY$ | API_KEY, AWS_ACCESS_KEY_ID |
| .*_TOKEN$ | GITHUB_TOKEN, AUTH_TOKEN |
| .*_SECRET$ | CLIENT_SECRET, JWT_SECRET |
| .*_PASSWORD$ | DB_PASSWORD, ADMIN_PASSWORD |
| .*_CREDENTIAL.* | GCP_CREDENTIALS, AZURE_CREDENTIAL_FILE |
Redaction Method
- Collect all environment variable names matching patterns
- Get their values
- In any output string, replace occurrences of those values with
[REDACTED] - Handle partial matches and URL-encoded variants
Configuration Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| enabled | boolean | false | Enable redaction |
| patterns | string[] | (see above) | Regex patterns for variable names |
| additionalVariables | string[] | [] | Explicit variable names to redact |
| excludeVariables | string[] | [] | Variables to exclude from redaction |
| redactionString | string | [REDACTED] | Replacement text |
| logRedactions | boolean | false | Log when redaction occurs (for debugging) |
Alternative Solutions
- Minimal environment: Run hooks with a stripped-down environment. This breaks many legitimate hooks that need environment context.
- Sandboxed execution: Run hooks in containers or sandboxes. Significant complexity and performance overhead.
- Manual filtering in hooks: Each hook implements its own redaction. Inconsistent and error-prone.
- Documentation only: Warn users about the risk. Doesn't prevent accidents.
Priority
Medium - Would be very helpful
Important for security-conscious organizations but not blocking for basic usage.
Feature Category
Configuration and settings
Use Case Example
Scenario: Preventing accidental secret exposure
- Developer creates a debugging hook that logs all input:
``bash``
#!/bin/bash
echo "Hook input: $(cat)"
echo "Environment: $(env)" # Dangerous!
- Without redaction, this exposes
ANTHROPIC_API_KEY,GITHUB_TOKEN, etc.
- With
environmentVariableRedactionenabled:
````
Hook input: {"session_id": "abc123", ...}
Environment: ANTHROPIC_API_KEY=[REDACTED]
GITHUB_TOKEN=[REDACTED]
PATH=/usr/bin:/bin
...
- Secrets are protected even from careless hook code
Scenario: Secure plugin ecosystem
- Organization uses third-party Claude Code plugins
- They can't audit every plugin's hook implementation
- Enable
environmentVariableRedactionorganization-wide - Even if a plugin tries to exfiltrate secrets via stdout/stderr, values are redacted
- Provides defense-in-depth against malicious or buggy plugins
Scenario: Compliance logging
- Enterprise requires logging all Claude Code activity
- Logs may be stored in systems with broader access
- Environment variable redaction ensures secrets don't end up in logs
- Audit trail is complete without exposing credentials
Scenario: Error investigation
- Hook fails with an error
- Error message happens to include a connection string:
Connection failed: postgres://user:PASSWORD123@host/db - With redaction enabled:
Connection failed: postgres://user:[REDACTED]@host/db - Safe to share error logs with support or teammates
Additional Context
Prior Art
Gemini CLI implements this feature:
"Environment redaction: Enable variable filtering to prevent accidental secret leakage: 'environmentVariableRedaction': {'enabled': true}"
Their best practices documentation explicitly recommends enabling this for security.
Implementation Considerations
- Performance: Redaction scanning should be efficient (compile patterns once, scan efficiently)
- False positives: Some variable values may appear in legitimate output. Consider minimum length thresholds.
- Binary data: Handle non-text output appropriately
- Encoding: Handle URL-encoded, base64-encoded, and other encoded variants of secrets
- Partial matches: If a secret is part of a larger string, still redact it
- Enterprise defaults: Consider making this enabled by default in enterprise/managed deployments
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗