Skip to content

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.

Terminal window
# Start a session in sandbox mode
claude --sandbox
# Or enable permanently in settings.json
{
"sandbox": true
}

What Gets Isolated

ResourceSandbox Behavior
Filesystem writesConfined to sandbox boundary; writes outside require explicit allow
Network requestsBlocked by default; specific hosts can be allowlisted
Subprocess executionProcesses run inside the sandbox; cannot spawn outside
Environment variablesInherited 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.

Terminal window
# Set in shell profile for persistent effect
export CLAUDE_CODE_SUBPROCESS_ENV_SCRUB=1
# Or set per-session
CLAUDE_CODE_SUBPROCESS_ENV_SCRUB=1 claude

With 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 1 in 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)"
]
}
}
PatternWhat 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:

  1. Allow rules define the working surface (narrow + specific)
  2. 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.json

Files 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
managed-settings.d/02-model-restrictions.json
{
"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:

  1. Read the server’s tool manifest — what tools does it expose and what can they do?
  2. Check whether the server writes files, makes network requests, or accesses databases
  3. Confirm the server source is trustworthy — do not install MCP servers from unknown or unreviewed sources
  4. 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:

Terminal window
# 1. Start a sandbox session for the review
claude --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 boundary

This 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

ControlWhen to Apply
--sandboxPR reviews, untrusted code, CI/CD
CLAUDE_CODE_SUBPROCESS_ENV_SCRUB=1Any env with real secrets
Deny rules for destructive bashAll projects
Deny rules for system directory writesAll projects
Secrets in settings.local.json onlyAny project with credentials
MCP server review before installEvery new MCP server
Managed settingsTeams of 3+ developers