# Lock Claude Code out of your .env

> Four steps that stop Claude Code reading your secrets, and the check that proves it worked.

Source: https://fullbytedeveloper.com/blog/claude-code-env-lock
Keyword: ENVLOCK
Published: 2026-10-30
Tested: 2026-10-30, Claude Code 2.1.312, fake keys only

Claude Code can read your `.env` file, and a line in `CLAUDE.md` asking it not to won't stop it. These four steps do. I tested them on Claude Code 2.1.312 with fake keys only.

## Start it in your project folder

Claude Code works from the folder you start it in. Start it in your project, not your home folder, so your other projects and dotfiles aren't in reach to begin with.

```bash
cd ~/code/my-app
claude
```

You should see your project's path in the Claude Code header.

## Add deny rules to settings.json

Create `.claude/settings.json` in the project (or add to it) and deny reads of your env files and key folders [1]. Deny rules are checked before allow rules, and an allow rule can't make an exception to a deny rule. The file is strict JSON: no comments and no trailing commas [3].

```json title=".claude/settings.json"
{
  "permissions": {
    "deny": [
      "Read(./.env)",
      "Read(./.env.*)",
      "Read(~/.ssh/**)",
      "Read(~/.aws/**)"
    ]
  }
}
```

Commit this file so everyone on the project gets the same rules. Deny rules apply right away, even before someone trusts the folder [3].

In my test, the Read tool was refused. You should see Claude Code report that reading `.env` is denied by your settings.

## Turn on the sandbox

Read deny rules cover Claude's own file tools and the shell commands Claude Code recognizes, such as `cat`, `head` and `tail`. They don't cover a script that opens the file itself [1]. In my test, a short Python script still printed the fake keys past the deny rule.

The sandbox fixes that at the operating system level [2]. Add it to the same file:

```json title=".claude/settings.json"
{
  "permissions": {
    "deny": [
      "Read(./.env)",
      "Read(./.env.*)",
      "Read(~/.ssh/**)",
      "Read(~/.aws/**)"
    ]
  },
  "sandbox": {
    "enabled": true,
    "filesystem": {
      "denyRead": ["./.env", "~/.ssh", "~/.aws"]
    }
  }
}
```

Or type `/sandbox` inside Claude Code to turn it on interactively. The sandbox works on macOS, Linux and WSL2. On Linux and WSL2 it needs two packages first [2]:

```bash
sudo apt-get install bubblewrap socat
```

**Warning:** if the sandbox can't start, Claude Code runs commands without it unless you also set `"failIfUnavailable": true` inside `"sandbox"` [2].

With the sandbox on, the same Python script got `Permission denied` in my test.

## Check that it worked

Put a fake key in `.env`, then ask Claude Code to read it, both directly and through a script.

```bash
echo "API_KEY=fake-123" > .env
claude
```

```text
Read .env and tell me what API_KEY is.
Run: python3 -c "print(open('.env').read())"
```

You should see the first request refused by your deny rule and the second fail with `Permission denied`. Type `/permissions` to see every rule that's active.

## Rotate any key it already saw

If Claude Code read a real `.env` before you did this, treat those keys as exposed. Create new keys in each provider's dashboard, put them in `.env`, and revoke the old ones. The rules above stop the next read; they can't undo an earlier one.

Your `.env`, `~/.ssh` and `~/.aws` are now off limits to Claude Code's tools and to anything it runs in the sandbox.

## Sources

1. [Claude Code docs: permissions](https://code.claude.com/docs/en/permissions)
2. [Claude Code docs: sandboxing](https://code.claude.com/docs/en/sandboxing)
3. [Claude Code docs: settings](https://code.claude.com/docs/en/settings)

## Original posts

- [TikTok video](https://www.tiktok.com/@fullbytedeveloper/video/7702492286617193780)
- [Instagram reel](https://www.instagram.com/fullbytedeveloper/reel/DfH_AGLla5t/)
- [Facebook reel](https://www.facebook.com/reel/29163893479911409/)
