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.
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,
.envfiles, 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:
- 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. - 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. - Blocked commands. When an AI agent is detected, NoxKey blocks
--raw,--copy,load,env,export, andbundleentirely. The agent can use secrets — it just can't extract them. - 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.
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.jsonlets 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.
| Check | How |
|---|---|
| No .env files in project | find . -name ".env*" -not -path "*/node_modules/*" |
| Secrets in Keychain | noxkey ls myorg/project/ |
| DLP guard active | noxkey guard status |
| Permission boundaries set | Check .claude/settings.json |
| Pre-commit hook installed | cat .git/hooks/pre-commit |
| No secrets in git history | git 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
.envfiles, 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,.envfiles 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
securitycommand), 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.
.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.
Free. No account. No cloud. Just your Keychain and Touch ID.