[BUG] Claude Code reads process environments and hardcodes credentials in terminal output

Resolved 💬 5 comments Opened Mar 4, 2026 by Dany-Axhor Closed May 1, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

Related Issues

  • #2142 (API keys exposed to version control — different vector)
  • #24185 (.env files hardcoded into scripts — different vector)

What's Wrong?

When Claude Code needs an API key to make HTTP requests (e.g., curl calls to internal services), it proactively reads credentials from running process environments via /proc/<PID>/environ, displays the credential value in the terminal output, and then hardcodes the raw secret into subsequent curl commands.

This creates permanent credential exposure in:

  • Terminal scrollback buffer
  • Session logs
  • Screen captures / recordings
  • Any tool that captures Claude Code output

The model does this even when secure credential stores (e.g., systemd-creds) are available and configured. There is no built-in guardrail to prevent this behavior.

Steps to Reproduce

  1. Run a service that has API keys in its environment (e.g., a systemd service with Environment=API_KEY=secret-value)
  2. Ask Claude Code to query that service's API
  3. Claude Code will:
  • Run cat /proc/<PID>/environ | tr '\0' '\n' | grep API_KEYdisplays the key in terminal output
  • Then use the key directly in a curl command: curl -H "X-API-Key: secret-value-in-plain-text" http://...hardcodes the key in the command

Expected Behavior

Claude Code should never display credential values in terminal output. When it needs to use a credential:

  1. Capture the value in a shell variable without displaying it:

``bash
KEY=$(grep API_KEY /proc/$PID/environ_file | cut -d= -f2)
curl -H "X-API-Key: $KEY" http://...
``

  1. Or better, use the secure credential store directly:

``bash
KEY=$(systemd-creds decrypt --name=service.api-key /path/to/cred -)
curl -H "X-API-Key: $KEY" http://...
``

Severity

HIGH — Credentials are silently exposed with no warning. The user may not notice until the key is compromised. In our case, we had to:

  • Rotate all exposed keys
  • Build a custom PreToolUse hook to block dangerous patterns
  • Create a wrapper script to handle credentials safely

Workaround

We implemented a PreToolUse hook that blocks Bash commands containing:

  • Process environment reading patterns
  • Hardcoded API key patterns (regex on known prefixes)
  • systemd-creds decrypt without variable capture
  • Direct reads of credential files

This should arguably be a built-in behavior, not something users need to implement themselves.

Proposed Fix

  1. Built-in credential detection: Claude Code should recognize when it's about to display a credential value and redact it from terminal output
  2. Secure-by-default patterns: When the model needs credentials, it should always capture them in variables, never inline them in commands
  3. PreToolUse guardrail: Ship a default hook (or built-in check) that blocks commands reading process environments or containing patterns matching common API key formats

Environment

  • Claude Code version: latest (2026-03-04)
  • Model: claude-opus-4-6
  • OS: Ubuntu 24.04 (VPS)
  • Credential store: systemd-creds (encrypted at rest)

View original on GitHub ↗

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