Claude Code operates on a permission-based security model that balances productivity with protection. By default, it is read-only and asks for explicit approval before making changes to your system. This guide covers how to configure permissions, enable sandboxing for enhanced security, and set up safe execution environments across different platforms.
Understanding the Security Model
Claude Code's security model follows an "ask before act" posture:
- File reads: Allowed by default
- File edits: Shown as diffs for review before approval
- Shell commands: Require approval (except safe commands like
echoorcat) - Network access: Controlled through sandbox proxy when enabled
This approach protects against prompt injection attacks, where malicious instructions embedded in code or data could trick Claude into performing harmful actions.
Permission Modes
Claude Code has four permission modes:
| Mode | Description | Use Case |
|---|---|---|
| default | Allows reads, asks before other operations | Normal development |
| plan | Analyze only - cannot modify files or execute commands | Code review, planning |
| acceptEdits | Bypass permission prompts for file edits only | Trusted prototyping |
| bypassPermissions | No permission prompts (dangerous) | Isolated containers only |
To set the default mode on startup, add to your settings.json:
{
"defaultMode": "default"
}
Configuring Permissions with settings.json
The settings.json file is the primary way to configure lasting permission rules.
Settings File Locations
Settings are loaded hierarchically, with later files taking precedence:
- User settings:
~/.claude/settings.json- applies to all projects - Project settings:
.claude/settings.json- shared with team (check into source control) - Local settings:
.claude/settings.local.json- personal overrides (add to.gitignore) - Managed settings:
managed-settings.json- enterprise policies (cannot be overridden)
Permission Rule Types
{
"permissions": {
"allow": [
"Bash(npm run lint)",
"Bash(npm run test:*)",
"Read(~/.zshrc)"
],
"ask": [
"Bash(git push:*)",
"Bash(docker run:*)"
],
"deny": [
"Bash(curl:*)",
"Read(./.env)",
"Read(./secrets/**)"
]
}
}
Rule evaluation order:
- deny - Block regardless of other rules
- allow - Permit if matched
- ask - Prompt for approval
Pattern Syntax
For Read permissions, use gitignore-style patterns:
Read(**/.env)- Match.envfiles in any directoryRead(**/*.key)- Match files with.keyextensionRead(**/node_modules/**)- Match anything in node_modules
For Bash commands, use wildcards:
Bash(npm run test:*)- Matchnpm run test:unit,npm run test:e2e, etc.Bash(git commit:*)- Match git commit with any arguments
Recommended Security Configuration
{
"permissions": {
"allow": [
"Bash(npm run lint)",
"Bash(npm run test)",
"Bash(npm run build)",
"Bash(git status)",
"Bash(git diff:*)",
"Bash(git log:*)"
],
"deny": [
"Read(**/.env)",
"Read(**/.env.*)",
"Read(**/credentials.json)",
"Read(**/*.pem)",
"Read(**/*.key)",
"Bash(sudo:*)",
"Bash(su:*)",
"Bash(curl:*)",
"Bash(wget:*)",
"Bash(ssh:*)",
"Bash(rm -rf:*)"
]
},
"env": {
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": 1
}
}
Enabling Sandboxing
Sandboxing creates defined boundaries within which Claude can work more freely. According to Anthropic, sandboxing reduces permission prompts by 84% in internal usage while maintaining security.
Sandbox Features
- Filesystem isolation: Claude can only access or modify specific directories
- Network isolation: Claude can only connect to approved servers
- Process isolation: Restrictions apply to all subprocesses spawned by commands
- Credential protection: Git credentials never enter the sandbox
Enabling Sandbox Mode
Run the /sandbox command in Claude Code:
/sandbox
This opens a menu where you can choose between:
-
Auto-allow mode: Bash commands run inside the sandbox without requiring permission. Commands that cannot be sandboxed fall back to the regular permission flow.
-
Regular permissions mode: All bash commands go through the standard permission flow, even when sandboxed. This provides more control but requires more approvals.
How Sandbox Isolation Works
Filesystem isolation prevents access to sensitive directories:
- System files (
/etc,/usr, etc.) - User home directory secrets (
~/.ssh,~/.aws, etc.) - Only your project directory is accessible by default
Network isolation routes all traffic through a proxy:
- Only approved domains can be accessed
- New domain requests prompt for user confirmation
- Git operations use a separate proxy that verifies operations without exposing credentials
Platform-Specific Setup
macOS
macOS uses Seatbelt for sandbox enforcement. This is Apple's native sandboxing technology.
Requirements:
- macOS 10.15 (Catalina) or later
- Claude Code installed via native installer or Homebrew
Enabling sandbox:
/sandbox
The Seatbelt profile allows communication only to specific localhost ports where the proxies listen. All other network access is blocked.
Linux
Linux uses bubblewrap (bwrap) for containerization.
Requirements:
- bubblewrap installed:
sudo apt install bubblewrap(Debian/Ubuntu) orsudo dnf install bubblewrap(Fedora) - User namespaces enabled (most distributions have this by default)
Enabling sandbox:
/sandbox
Network requests are routed via Unix domain sockets (using socat for bridging). The network namespace is removed from the bubblewrap container, ensuring all traffic goes through the proxies.
Docker environments:
If running Claude Code inside Docker, the standard sandbox may not work due to missing privileged namespaces. Use the enableWeakerNestedSandbox setting:
{
"sandbox": {
"enableWeakerNestedSandbox": true
}
}
Warning: This considerably weakens security and should only be used when Docker provides additional isolation.
Windows
Native Windows does not currently support the /sandbox command. The sandbox relies on Linux (bubblewrap) and macOS (Seatbelt) primitives that do not have Windows equivalents.
Options for Windows users:
-
Use WSL 2: The recommended approach for Windows users who need sandboxing:
# Install WSL 2 if not already installed wsl --install # Install bubblewrap in your WSL distribution sudo apt install bubblewrap # Run Claude Code in WSL claude /sandboxNote: WSL 1 does not support sandboxing. Ensure you are using WSL 2.
-
Use Docker: Run Claude Code in a Docker container for isolation:
docker run -it --rm \ -v $(pwd):/workspace \ docker/sandbox-templates:claude-code -
Use native Windows without sandbox: You can still use Claude Code on native Windows with the standard permission system. Configure strict
denyrules insettings.jsonto protect sensitive files.
Using Docker for Maximum Isolation
For workflows requiring unattended operation, Docker provides the safest environment for using --dangerously-skip-permissions.
Why Use Docker?
- Filesystem isolation: Claude cannot touch your host system files
- Network isolation: Can be configured to block all external access
- Blast radius reduction: Even if Claude goes rogue, damage is contained
Docker Sandbox Setup
Option 1: Official Docker sandbox template
docker run -it --rm \
-v $(pwd):/workspace \
docker/sandbox-templates:claude-code
This image includes:
- Claude Code with automatic credential management
- Development tools
- Runs as non-root user with sudo access
--dangerously-skip-permissionsenabled by default
Option 2: DevContainer
Create .devcontainer/devcontainer.json:
{
"name": "Claude Code Sandbox",
"image": "docker/sandbox-templates:claude-code",
"workspaceFolder": "/workspace",
"mounts": [
"source=${localWorkspaceFolder},target=/workspace,type=bind"
],
"postStartCommand": "claude"
}
Option 3: Custom Dockerfile
FROM node:20-slim
RUN npm install -g @anthropic-ai/claude-code
# Create non-root user
RUN useradd -m -s /bin/bash agent
USER agent
WORKDIR /workspace
# Disable network access (optional)
# Run with: docker run --network none
ENTRYPOINT ["claude", "--dangerously-skip-permissions"]
Network Isolation in Docker
For maximum security, disable network access:
docker run -it --rm \
--network none \
-v $(pwd):/workspace \
your-claude-image
Handle git operations on the host machine before and after running Claude in the container.
Best Practices
Do
- Enable sandboxing for day-to-day development
- Use specific allow rules rather than broad patterns
- Test your permission rules to verify they work as expected
- Run Claude Code in Docker for unattended or high-risk tasks
- Review diffs carefully before approving file edits
- Keep Claude Code updated for the latest security fixes
Do Not
- Never use
--dangerously-skip-permissionsoutside of isolated containers - Never allow write access to executable directories or shell configs
- Never whitelist sensitive file patterns like
.envor credentials - Do not rely solely on
denyrules - use Docker for critical isolation - Do not expose Docker socket (
/var/run/docker.sock) to the sandbox
Security Checklist
- Configure
denyrules for sensitive files (.env, keys, credentials) - Enable sandboxing with
/sandboxcommand - Use specific
allowrules for trusted commands - Run in Docker for unattended tasks
- Review and test permission rules regularly
- Keep Claude Code updated
Troubleshooting
Sandbox Not Available
If /sandbox returns "Unknown slash command":
- Check your platform: Sandboxing requires macOS or Linux (including WSL 2)
- Update Claude Code: Run
claude --versionand update if needed - Install bubblewrap (Linux):
sudo apt install bubblewrap
Permission Rules Not Working
If deny rules seem to be ignored:
- Check rule syntax: Ensure patterns match the actual paths
- Test with explicit paths: Try
Read(/absolute/path/.env)instead of patterns - Use PreToolUse hooks: For critical protection, implement a hook that intercepts tool calls:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Read",
"hooks": ["check-sensitive-files"]
}
]
}
}
Network Access Blocked
If legitimate network requests are blocked in sandbox mode:
- Check allowed domains: The proxy only allows pre-approved domains
- Request approval: New domains will prompt for user confirmation
- Configure trusted domains: Add frequently-used domains to your configuration