When using Claude Code CLI, the agent runs in your terminal and has access to your local files. To prevent Claude from reading .env files and accidentally sending your secrets to Anthropic's APIs, you can set up a PreToolUse hook.
Save this bash script to ~/.claude/hooks/guard-env.sh and make it executable (chmod +x).
#!/usr/bin/env bash
# PreToolUse hook (Read/Bash/Grep): blocks tool calls touching secret/credential
# files or dumping the environment.
#
# .env-style names are checked per token, so an allowlisted name elsewhere in
# the payload can't be smuggled in to defeat the guard (e.g. `cat .env .env.example`).
PAYLOAD=$(cat)
block() {
printf '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny","permissionDecisionReason":"SECURITY: Blocked %s. Read .env.example or a schema file (env.ts/env.mjs) instead."}}\n' "$1"
exit 0
}
# Secret paths and env dumps — any match blocks.
DENIED='\.dev\.vars|\.pem\b|\.p12\b|\.pfx\b|\.ppk\b|\.p8\b|\bid_rsa\b|\bid_dsa\b|\bid_ed25519\b|\bid_ecdsa\b|\.ssh/|\.gnupg/|\.aws/|\.kube/config|\.docker/config|\.config/gh/|\.htpasswd\b|\.tfstate\b|\.[a-z0-9]+_history\b|(~|'"$HOME"')/\.(netrc|npmrc|pypirc|yarnrc|git-credentials|pgpass|my\.cnf|cargo/credentials|config/git/credentials|codex/config\.toml)|/proc/[^[:space:]]*/environ|\bprintenv\b|(^|[[:space:];&|"])env[[:space:]]*($|\|)'
printf '%s' "$PAYLOAD" | grep -Eiq "$DENIED" && block "a secret file or env dump"
KEYFILE='["'"'"'][A-Za-z0-9._~/-]*(\.key|credentials\.(json|ya?ml|toml)|secrets\.(json|ya?ml|toml))["'"'"']|(/|\./|~/)[^[:space:]"'"'"'{}()$]*(\.key|credentials\.(json|ya?ml|toml)|secrets\.(json|ya?ml|toml))\b'
printf '%s' "$PAYLOAD" | grep -Eiq "$KEYFILE" && block "a key/credential file"
while IFS= read -r tok; do
case "${tok##*/}" in
.env.example|.env.template|.env.sample|.env.defaults|env.ts|env.mjs|env.d.ts) ;;
.env|.env.*|.envrc) block "a .env file" ;;
esac
done < <(printf '%s' "$PAYLOAD" | grep -Eio '[^[:space:]"'"'"';|&<>()]*\.env[A-Za-z0-9._-]*')
exit 0