All posts

Claude Code Security Best Practices — Protect Your Secrets and Your Codebase

We love Claude Code. It writes our tests, refactors our modules, debugs deploys we'd spend hours on manually. It's the best coding assistant we've ever used. But we also learned — the hard way — that it runs with your full user permissions. Every file, every command, every secret on your machine. If you can read it, so can Claude Code.

This isn't a scare piece. We're not here to warn you off Claude Code — we'd never ship without it. We're here to share what we do to keep our secrets safe while using it every day on production codebases.

Claude Code is a power tool. Like any power tool, the safety setup matters more than the tool itself.

What Claude Code can actually access

Claude Code isn't sandboxed. It runs as a subprocess in your terminal, inheriting your user permissions. Here's what that means:

  • Every file on your machine. Source code, config files, .env files, SSH keys, browser profiles — if your user account can read it, Claude Code can too. It doesn't need to be in the project directory.
  • Your terminal. It can run any shell command. curl, cat, env, printenv — whatever helps it answer your question. Including commands that output secrets.
  • Network access. It can make HTTP requests, install packages, clone repos. If a script phones home with debug info, your secrets could be in the payload.
  • Environment variables. Anything in your shell environment is visible. If you ran export STRIPE_KEY=sk_live_... earlier, Claude Code can see it.

None of this is a bug. Claude Code needs file and terminal access to be useful. The problem? Most of us have secrets scattered across our file systems with zero protection — and Claude Code treats them like any other context.

The risks we've seen firsthand

These aren't hypotheticals. We've watched every one of these happen. Some of them happened to us.

Reading .env files for context

You ask Claude Code to debug an API integration. It pulls in project files to understand the setup — config, routes, middleware. Then it grabs .env. Your database password and API keys land in the conversation log. We wrote about this in AI Agents Can Read Your .env Files.

Printing secrets in debug output

You ask it to debug a 401. It runs curl -v with your API key in the Authorization header. The full request — including the key — gets printed and logged. Helpful debugging. Terrible secret hygiene.

Hardcoding tokens in generated code

Claude Code has seen your API key in the context window. You ask it to write a config file. Instead of referencing an environment variable, it helpfully drops in the real value. You commit. Push. Now it's in your git history forever.

Leaking secrets through error messages

A script fails. The error dump includes connection strings, tokens, or credentials. Claude Code reads the output to help you fix it. The secrets are now in the conversation.

Exposing environment variables

Claude Code runs env or printenv to understand your setup. If your secrets are loaded as environment variables, they all show up. Every single one.

We catalogued more leak vectors in 6 Ways AI Agents Leak Your Secrets. The pattern's always the same: Claude Code is doing exactly what you asked, and your secrets are just collateral context.

Four things we do on every machine

This is our actual setup. Not theoretical — this is what runs on our dev machines right now.

1. Move secrets out of .env files and into the Keychain

This is the single biggest win. No file on disk means no file to read. We use NoxKey to store everything in the macOS Keychain, protected by Touch ID.

# Import existing secrets
$ noxkey import myorg/project .env
✓ Imported 5 secrets

# Delete the plaintext file
$ rm .env

# Load secrets when you need them
$ eval "$(noxkey get myorg/project/STRIPE_KEY)"

The secret goes straight from the Keychain into your shell. It never touches disk. Claude Code can use it through process.env, but there's no .env to read. We migrated all our projects in an afternoon — 47 .env files, gone.

2. Install the DLP guard hook

Even with secrets off disk, they can still leak. A debug trace, a log file, a verbose HTTP request — secrets find ways into terminal output. The DLP guard catches them.

$ noxkey guard install

One command. It installs a PostToolUse hook in Claude Code that scans every tool output against fingerprints of your stored secrets. If a secret value shows up in any output, it's blocked before entering the conversation.

# What happens behind the scenes:
# 1. Claude Code runs: curl -v https://api.stripe.com/v1/charges
# 2. Output contains: "Authorization: Bearer sk_live_51ABC..."
# 3. Guard matches fingerprint of myorg/project/STRIPE_KEY
# 4. Blocked — secret never enters the conversation context

The guard uses 8-character prefix fingerprints from noxkey peek. No config beyond the install command. It just runs.

3. Use Claude Code's permission boundaries

Claude Code has a built-in permissions system. Use it. In your project's .claude/settings.json:

{
  "permissions": {
    "allow": [
      "Read(**/*.ts)",
      "Read(**/*.json)",
      "Write(src/**)",
      "Bash(npm test)",
      "Bash(npm run build)"
    ],
    "deny": [
      "Read(**/.env*)",
      "Read(~/.ssh/*)",
      "Read(~/.aws/*)",
      "Bash(cat .env*)",
      "Bash(printenv)"
    ]
  }
}

This isn't bulletproof — a determined prompt could find workarounds. But it catches the most common accidental reads and sends a clear signal about what's off-limits. Think of it as a seatbelt, not an airbag.

4. Review before you push

Sounds obvious. Easy to skip when Claude Code has made 30 changes across 12 files. Before every push, we run:

# Check for hardcoded secrets in staged changes
$ git diff --staged | grep -iE "(sk_live|sk_test|AKIA|ghp_|password\s*=)" 

Better yet, install a pre-commit hook that does this automatically. One leaked key in a public repo and your day is ruined. It's always on a Friday.

How NoxKey makes this automatic

We built NoxKey because we got tired of doing all of this manually. Here's what happens when Claude Code requests a secret through NoxKey:

  1. Process-tree detection. NoxKey walks up the process hierarchy — noxkey → bash → claude → zsh → Terminal. It spots Claude Code in the chain and switches to restricted mode automatically.
  2. Encrypted handoff. Instead of returning the raw secret, NoxKey writes it to an AES-256-CBC encrypted, self-deleting temp script. Claude Code gets back source '/tmp/...'. The secret loads into the shell. The raw value never appears in the conversation.
  3. Blocked commands. When an AI agent is detected, NoxKey blocks --raw, --copy, load, env, export, and bundle entirely. The agent can use secrets — it just can't extract them.
  4. DLP guard. The PostToolUse hook scans every piece of output. If a secret leaks through a log or debug trace, it's caught before entering the conversation.
Claude Code calls noxkey get Process tree: agent detected Encrypted self-deleting script Secret in env, never in context

The result: we tell Claude Code to deploy, run tests, call APIs — and it does all of it. Our secrets work. They're just invisible to the conversation.

What Claude Code gets right

Credit where it's due — Claude Code is better about security than most AI coding tools:

  • Permission prompts. It asks before running shell commands and writing files. You can review and deny.
  • Project-level settings. .claude/settings.json lets you configure allowed and denied operations per project.
  • No cloud IDE. It runs locally. Your files don't get uploaded to a remote workspace. That's already better than browser-based AI tools.
  • Conversation isolation. Each session starts fresh. Secrets from one conversation don't bleed into the next (unless they're in files it reads again).

The gap isn't in Claude Code's design. It's in our habits. We've trained ourselves to put secrets in .env files because it was easy. Now that our terminals have AI assistants reading everything, "easy" and "safe" aren't the same thing anymore.

Quick security checklist

Bookmark this. Run through it for every project you use with Claude Code.

CheckHow
No .env files in projectfind . -name ".env*" -not -path "*/node_modules/*"
Secrets in Keychainnoxkey ls myorg/project/
DLP guard activenoxkey guard status
Permission boundaries setCheck .claude/settings.json
Pre-commit hook installedcat .git/hooks/pre-commit
No secrets in git historygit log -p | grep -iE "sk_live|AKIA|ghp_"

Frequently asked questions

Is Claude Code safe to use?
Yes — with the right setup. Claude Code itself is well-designed and runs locally. The risk isn't the tool, it's how your secrets are stored. If you keep API keys in .env files, any tool with file access can read them. Move secrets to the macOS Keychain, install a DLP guard, and Claude Code becomes one of the safest ways to work with an AI assistant.
Can Claude Code access files outside my project directory?
Yes. It runs with your user permissions, so it can read anything your account has access to — ~/.ssh, ~/.aws/credentials, .env files in other projects. Permission boundaries help, but the real fix is keeping secrets out of plaintext files entirely.
Does Claude Code send my code to Anthropic's servers?
Conversation contents are sent to Anthropic's API for processing. On paid plans, Anthropic states this data isn't used for training. But "not used for training" doesn't mean "not logged." Secrets that enter the conversation may still appear in server logs. The safest approach: keep secrets out of the conversation entirely with encrypted handoff.
What's the difference between .claude/settings.json deny rules and NoxKey?
Deny rules tell Claude Code what it shouldn't do — they're a soft control. NoxKey makes it so secrets aren't there to be read in the first place — that's a hard control. Use both. Defense in depth.
Can I use Claude Code safely without NoxKey?
You can improve things without NoxKey by moving secrets to the macOS Keychain manually (using the security command), setting up permission boundaries, and being careful about what you ask Claude Code to do. NoxKey automates all of this — process-tree detection, encrypted handoff, DLP scanning — so you don't have to think about it. But the principles work with any credential store.
Key Takeaway
We wouldn't work without Claude Code — it's a genuine productivity multiplier. But it has full access to your file system and terminal. Move secrets from .env files to the macOS Keychain, install a DLP guard, use permission boundaries, and review every change before pushing. NoxKey handles all of this automatically with process-tree detection and encrypted handoff.

Download NoxKey

Free. No account. No cloud. Just your Keychain and Touch ID.