Security Hardening
Claude Code ships with sensible defaults, but production use — especially in teams, CI/CD pipelines, or when reviewing external contributions — requires deliberate security configuration. This page covers the layered controls available beyond the defaults.
Sandboxing
Sandbox mode applies OS-level isolation to Claude’s actions: filesystem writes, network requests, and subprocess execution are confined to a restricted boundary. Anything outside that boundary requires explicit allowlisting.
# Start a session in sandbox modeclaude --sandbox
# Or enable permanently in settings.json{ "sandbox": true}What Gets Isolated
| Resource | Sandbox Behavior |
|---|---|
| Filesystem writes | Confined to sandbox boundary; writes outside require explicit allow |
| Network requests | Blocked by default; specific hosts can be allowlisted |
| Subprocess execution | Processes run inside the sandbox; cannot spawn outside |
| Environment variables | Inherited from parent, subject to scrubbing rules |
The Permission Reduction Effect
Sandbox mode dramatically reduces the surface area of permission prompts because Claude cannot attempt operations outside its boundary in the first place. Rather than Claude asking “can I write to /etc/hosts?”, the sandbox simply prevents the attempt. The result is a quieter, more predictable permission dialog experience.
Trade-offs
Sandbox mode is not free. Claude cannot write output files to directories outside the sandbox boundary without explicit configuration. Some tools (particularly MCP servers that interact with the broader filesystem) need to be allowlisted or will fail silently.
Before enabling sandbox in a project, confirm:
- Where Claude is expected to write output files
- Which MCP servers are in use and what filesystem access they need
- Whether any build scripts or test runners need paths outside the sandbox
When to Use Sandbox
Sandbox mode is most valuable in three scenarios:
Reviewing external PRs. Code from outside contributors may contain prompt injection attempts or malicious instructions embedded in comments or docs. Sandbox ensures that even if Claude is manipulated, the blast radius is contained.
Running untrusted code. If the task involves executing code you did not write — reproducing a bug from a user report, testing a third-party library — sandbox prevents that code from escaping its intended scope.
CI/CD pipelines. Automated pipelines benefit from the reduced permission surface. Sandbox gives the pipeline a clear, auditable execution boundary.
CLAUDE_CODE_SUBPROCESS_ENV_SCRUB
Claude spawns subprocesses frequently — bash commands, node scripts, test runners. Without scrubbing, every subprocess inherits the full environment of the parent process, including any secrets you have set as environment variables.
# Set in shell profile for persistent effectexport CLAUDE_CODE_SUBPROCESS_ENV_SCRUB=1
# Or set per-sessionCLAUDE_CODE_SUBPROCESS_ENV_SCRUB=1 claudeWith scrubbing enabled, Claude strips API keys, tokens, and recognized secret patterns from subprocess environments before spawning them. The variables remain available to Claude’s own process — just not to anything it forks.
Note: Set this to
1in every environment where secrets live in env vars: local development with real API keys, staging, CI/CD. The only safe place to omit it is a fully sandboxed environment with no real credentials.
Settings File Security
Claude Code has a layered settings hierarchy:
~/.claude/settings.json ← global defaults (your machine).claude/settings.json ← project-level (committed to git).claude/settings.local.json ← personal overrides (git-ignored)Priority order: local overrides project overrides global. Later layers win.
The Critical Rule
.claude/settings.json is committed to your repository. Everyone who clones the repo gets it. Never put API keys, tokens, webhook URLs, or any credential in this file.
// settings.json — safe to commit{ "model": "claude-sonnet-4-6", "sandbox": true, "permissions": { "allow": ["Read(**)", "Write(src/**)"], "deny": ["Bash(rm -rf *)", "Write(/etc/**)"] }}// settings.local.json — git-ignored, safe for credentials{ "env": { "ANTHROPIC_API_KEY": "sk-ant-..." }}Confirm .claude/settings.local.json is in your .gitignore before adding anything sensitive to it.
Deny Rules
Deny rules have the highest precedence in the permissions system. They override allow rules unconditionally — there is no way for a prompt or a tool call to circumvent a deny rule.
{ "permissions": { "deny": [ "Bash(rm -rf *)", "Bash(sudo *)", "Write(/etc/**)", "Write(/usr/**)", "Bash(curl * | bash)", "Bash(wget * | sh)" ] }}Recommended Deny Patterns
| Pattern | What It Blocks |
|---|---|
Bash(rm -rf *) | Recursive delete with no target restriction |
Bash(sudo *) | Any privileged command execution |
Write(/etc/**) | System configuration file writes |
Write(/usr/**) | System binary and library writes |
Bash(curl * | bash) | Remote code execution via pipe |
Bash(DROP TABLE *) | Destructive SQL via bash |
Defense in Depth Strategy
Do not rely on allow rules alone. Allow rules define what Claude can do. Deny rules define what it absolutely cannot do regardless of any other configuration. Use both:
- Allow rules define the working surface (narrow + specific)
- Deny rules define the hard floor (broad + conservative)
If a permission falls through the allow rules without explicit coverage, it hits the deny layer. If it is not denied, Claude will ask. This three-layer model (allow → deny → ask) gives you predictable behavior for known patterns and explicit confirmation for everything else.
Managed Settings (Enterprise and Teams)
For teams that need to enforce consistent policies across all developers, managed settings provide org-level configuration that individual developers cannot override.
~/.claude/managed-settings.json ← single managed file~/.claude/managed-settings.d/ ← drop-in directory for multiple policy files ├── 01-base-policy.json ├── 02-model-restrictions.json └── 03-security-rules.jsonFiles in managed-settings.d/ are applied in alphabetical order. Later files override scalar values; arrays are concatenated and deduplicated.
Use Cases
- Enforce an approved model list (prevent use of non-vetted models)
- Require sandbox mode for all sessions
- Apply consistent deny rules across all developer machines
- Restrict tool access to approved MCP servers only
- Prevent developers from disabling safety checks in their local settings
{ "allowedModels": [ "claude-sonnet-4-6", "claude-opus-4-6" ], "permissions": { "deny": [ "Bash(rm -rf *)", "Write(/etc/**)" ] }}Managed settings are read before user settings and cannot be overridden by project or local settings files.
MCP Server Permissions
MCP servers get broad tool access by default. Review what each server can do before enabling it.
// Enable project MCP servers for the whole team{ "enableAllProjectMcpServers": true}Before enabling any MCP server:
- Read the server’s tool manifest — what tools does it expose and what can they do?
- Check whether the server writes files, makes network requests, or accesses databases
- Confirm the server source is trustworthy — do not install MCP servers from unknown or unreviewed sources
- For servers with filesystem access, verify their working directory scope
Note: An MCP server with filesystem write access and no scope restriction is equivalent to giving an external process write access to your whole project. Treat MCP server installation with the same scrutiny as adding a production dependency.
Bash Sandboxing for PR Review
A specific workflow for reviewing PRs from external contributors combines multiple controls:
# 1. Start a sandbox session for the reviewclaude --sandbox --label "pr-review-1234"
# 2. Claude can read and analyze the PR diff — no write access outside sandbox# 3. If Claude runs any code from the PR, it runs inside the sandbox# 4. Prompt injection attempts in PR comments cannot affect files outside sandbox boundaryThis pattern is recommended any time you are reviewing code where you do not fully trust the source — open source contributions, bounty submissions, code from new team members before trust is established.
Security Hardening Checklist
| Control | When to Apply |
|---|---|
--sandbox | PR reviews, untrusted code, CI/CD |
CLAUDE_CODE_SUBPROCESS_ENV_SCRUB=1 | Any env with real secrets |
| Deny rules for destructive bash | All projects |
| Deny rules for system directory writes | All projects |
Secrets in settings.local.json only | Any project with credentials |
| MCP server review before install | Every new MCP server |
| Managed settings | Teams of 3+ developers |