Keeping secrets from Claude Code

How to keep your .env files safe from AI coding assistants

UPDATE: This post blew up! But I discovered a FAR SUPERIOR approach. You still might like this! But bubblewrap is faster and more flexible.

https://patrickmccanna.net/a-better-way-to-limit-claude-code-and-other-coding-agents-access-to-secrets/


Someone posted online:

“I like how Claude Code casually reads my .env file.”

This is an accurate assessment of Claude Code. Claude Code reads .env files by default. It loads your API keys, database passwords and tokens into memory without asking.

Is this unappealing to you? Here’s how to manage that risk.

The Problem

Claude Code can read .env files automatically. If you run it without -dangerously-skip-permissions, normally it’ll ask permission for access. But what if claude stops acting normal?

Should the secrecy of your file rely on a system that prevents access to your file till you just type in the phrase ‘yes’?

How is it possible that claude code can’t access the file some times- and other times it can?

It’s possible because you’re logged in and running claude under your user account. Claude has all the permissions it needs to masquerade as you! Claude always had access to the file! It’s just being polite. The politeness of LLMs cannot be relied upon. When you run claude this way, any file accessible by you is accessible by claude.

Claude code is not supposed to break out of the Current Working Directory. But what technical constraints prevent it? If you run claude under your account, there’s no Linux/Mac OS control that prevents it from getting around to the photos/docs you have access to.

You’re trusting Claude to be polite and behave the way you expect.

If you invoke Claude (or any coding agent) under your user account, you’re trusting trust. Don’t despair! Here’s how to run Claude when you’re working on systems that demand safety.

The First Defense: A Separate User

Give Claude its own identity. Create the ‘Claude’ Group and User accounts.

On Linux:

# Create a group for Claude
sudo groupadd claude

# Create a user with no home directory privileges beyond basics
sudo useradd -m -g claude -s /bin/bash claude

# Set a password (you’ll need it for sudo later)
sudo passwd claude

On macOS:

# Create a group (find an unused GID first)
sudo dscl . -create /Groups/claude
sudo dscl . -create /Groups/claude PrimaryGroupID 400

# Create the user
sudo dscl . -create /Users/claude
sudo dscl . -create /Users/claude PrimaryGroupID 400
sudo ddcl . -create /Users/claude UserShell /bin/bash
sudo dscl . -create /Users/claude NFSHomeDirectory /Users/claude
sudo dscl . -create /Users/claude UniqueID 400

# Create home directory and set ownership
sudo mkdir -p /Users/claude
sudo chown claude:claude /Users/claude

# Set password
sudo passwd claude

The claude user now exists- run claude as it’s own user and keep the secrets files outside the permissions of the claude user.

Lock Down Your .env Files

Your secrets need permissions that exclude the claude user.

# Navigate to your project
cd /path/to/your/project

# Set ownership to yourself
chown $(whoami):$(whoami) .env

# Lock Down Your .env Files
# Remove all permissions for others
# Owner can read and write.
# Group and others get nothing

chmod 600 .env

The 600 permission means only you can read the file. The claude user belongs to a different group.

For extra certainty, explicitly deny the claude group:

# make sure .env is owned by your primary group

chown $(whoami):$(id -gn) .env chmod 640 .env

Verify your work:

ls -la .env

You should see something like -rw------- or -rw-r-----. The important part: no permissions on the right side for “others.”

Run Claude under the Claude user account

Become claude! Claude now runs with our claude user’s permissions. Your secrets remain invisible to the claude user because you’ve acl’d away access to the .env file

# Switch to claude user and run Claude Code

sudo -u claude claude

That’s it. sudo -u claude runs the command that follows as the claude user. Claude Code launches. If it tries to read your .env file, it’ll get a permissions denied error it can’t overcome.

For convenience, create an alias:

# Add to your .bashrc or .zshrc alias
claudecode=’sudo -u claude claude’

Now you type claudecode and everything’s safe

Summarizing:

# One-time setup (Linux)
sudo groupadd claude
sudo useradd -m -g claude -s /bin/bash claude
sudo passwd claude

# Per-project setup
cd /your/project
chown $(whoami):$(whoami) .env
chmod 600 .env

# Daily usage
sudo -u claude claude

  • Create a dedicated user for claude
  • Set file permissions that exclude the claude user from access to sensitive files
  • Invoke claude with sudo -u claude. let the OS enforce boundaries

The claude user can read your source code. It can write to project directories if you grant that access. But it cannot touch files owned by you with restrictive permissions. The operating system enforces this.

In the next section, I’ll summarize Anthropic’s stated controls. When you go this route, you’re trusting Anthropic to not only respect your wishes, but to write code so secure that it always and only does what they intend. All software has mistakes, even Anthropic’s. Buyer beware.

I include this next section out of respect for Anthropic- but my judgement is that using the following approach will eventually bite you in the butt.


The Second Defense: Deny Rules

Claude has mechanisms for restricting access. You’re trusting Anthropic to do the right thing correctly all the time. Anthropic has published mechanisms for telling Claude Code what it cannot touch. Do this before you write your first line of code. The configuration lives in ~/.claude/settings.json.

Create the file. Add these rules:

{ "permissions": 
    { "deny": [ 
        "Read(**/.env*)", 
        "Read(**/secrets/**)", 
        "Read(**/*credentials*)", 
        "Read(**/*secret*)", 
        "Read(~/.ssh/**)", 
        "Read(~/.aws/**)", 
        "Read(~/.kube/**)" ] 
    } }

The double asterisks catch nested directories. They catch the .env.local file you forgot you had.

Test your rules. Ask Claude Code to read your .env file. It should fail. If it reads the file anyway, something is wrong. Fix it before you continue.

The anthropic access controls are like putting a lock on your door. It keeps honest people honest. Locks can be picked. AI assistants can be influenced into circumventing their own controls.


An alternative approach: Containers

Containers are an approach for protecting secrets.

Run Claude Code inside a Docker container or a virtual machine. Give it access only to what it needs. The container is a sandbox the AI plays within. Your secrets stay outside the container. Make claude build the thing- it can have its own internal .env files- but for prod, you change your secrets.

Configure your container with read-only volumes for code. Mount nothing sensitive.

The AI agent can see project files in your container. It cannot see your home directory. It cannot see your SSH keys. It can’t probe through the Photos library in your home directory.

This approach follows the principle of least privilege. Grant minimum access required. Assume the worst.

My advice: Use operating system permissions, user accounts and groups

Leveraging Operating system access controls is defense in depth. Deny rules can be misconfigured. Vault integrations can fail. But Unix permissions have guarded secrets for a long time. You have to decide which risk is more probable: Kernel exploits that circumvent ACL’s or prompt engineering that pushes the Agent to access secrets. I’m going to put my resources into ACL’s and good OS hygenie. Then approaches don’t get distracted by clever prompts.

The Truth About AI Security

There is no going back. Claude is insanely useful. Coding agents write code faster than you can. They explain concepts clearly.

Coding agents are also prone to probabilistic outbursts. If you need to keep secrets, use deterministic/idempotent operating system access controls for preventing access.