Is Claude Code Safe? Security, Permissions & Sandbox Guide
Claude Code is a powerful agentic tool that can read files, write code, and run shell commands. This page explains exactly what it can and cannot do, how to configure the permission model, and how to harden it for team and production environments.
The Security Model at a Glance
| Question | Default behaviour | Configurable? |
|---|---|---|
| Read files | Any file your user can read | Yes — restrict to specific paths |
| Write files | Asks for approval per operation | Yes — allowlist/denylist paths |
| Run shell commands | Asks for approval per command | Yes — allowlist specific commands |
| Network access | None directly (Claude calls Anthropic API) | N/A for Claude itself |
| Send your code to Anthropic | Yes — required for the AI to work | Via Bedrock for AWS data residency |
| Access other users' files | No — limited by OS user permissions | N/A |
The Permissions System
Permissions are configured in .claude/settings.json (project-level) or ~/.claude/settings.json (user-level). Project settings override user settings for that project.
Allowlist — approve specific commands without prompting
// .claude/settings.json
{
"permissions": {
"allow": [
"Bash(npm test)",
"Bash(npm run lint)",
"Bash(git status)",
"Bash(git diff *)",
"Bash(git add *)",
"Bash(git commit *)",
"Write(src/**)",
"Read(**)"
]
}
}
Pattern matching uses glob syntax. Bash(git *) allows any git command. Write(src/**) allows writes only inside src/.
Denylist — always block, even if allowed elsewhere
{
"permissions": {
"deny": [
"Bash(rm -rf *)",
"Bash(git push --force *)",
"Bash(git reset --hard *)",
"Bash(DROP TABLE *)",
"Bash(curl * | bash)",
"Write(.env*)",
"Write(**/*.pem)",
"Write(**/*.key)"
]
}
}
Permission Modes
| Mode | Command flag | Behaviour | When to use |
|---|---|---|---|
| Default (interactive) | (none) | Asks approval for each operation | Daily development |
| Auto-approve | --dangerously-skip-permissions | No prompts — runs everything | Trusted automation only |
| Read-only | --permission-mode readonly (planned) | Read files, no writes, no shell | Code review / analysis |
| Print mode | --print | Non-interactive, uses allow/deny rules | CI/CD pipelines |
--dangerously-skip-permissions in automated pipelines. Always use explicit allowlists in CI instead.Protecting Sensitive Files
Add these to your denylist to prevent Claude from accidentally writing to sensitive files:
{
"permissions": {
"deny": [
"Write(.env)",
"Write(.env.*)",
"Write(**/.env)",
"Write(**/*.pem)",
"Write(**/*.key)",
"Write(**/*.p12)",
"Write(**/secrets.*)",
"Write(~/.ssh/*)",
"Write(~/.aws/*)"
]
}
}
.gitignore. Claude Code reads .gitignore and will avoid committing files listed there, but an explicit deny rule is a stronger safeguard.Data Privacy: What Gets Sent to Anthropic
When you ask Claude Code to read a file, the file contents are included in the API request to Anthropic. This is necessary — Claude cannot work on your code without seeing it.
What Anthropic's API does with your data
- Commercial API: Anthropic does not use API inputs to train models
- Data is processed to generate the response, then not retained
- Anthropic's terms cover API data handling — review for your compliance requirements
AWS Bedrock for data residency
# Route Claude Code through AWS Bedrock
# Data stays in your AWS region
export ANTHROPIC_BEDROCK=true
export AWS_REGION=eu-west-1
export AWS_ACCESS_KEY_ID=...
export AWS_SECRET_ACCESS_KEY=...
claude # now routes through Bedrock
Docker Sandbox (Maximum Isolation)
For the highest security posture — CI, untrusted codebases, or multi-tenant environments:
# Dockerfile for isolated Claude Code
FROM node:20-slim
RUN npm install -g @anthropic-ai/claude-code
WORKDIR /workspace
COPY . .
# Run non-root
RUN useradd -m claudeuser
USER claudeuser
ENTRYPOINT ["claude", "--print"]
# Run with restricted capabilities
docker run --rm \
--read-only \
--tmpfs /tmp \
--network none \
--cap-drop ALL \
--memory 2g \
-e ANTHROPIC_API_KEY=$ANTHROPIC_API_KEY \
-v $(pwd):/workspace:ro \
my-claude-sandbox \
"analyse this code for security issues"
--network none prevents any outbound network calls except the Anthropic API (if you mount credentials). Use for code analysis tasks where you want zero network exposure from the container.Team Configuration
Share a consistent security policy across your team by committing .claude/settings.json to your repository:
// .claude/settings.json — commit this
{
"permissions": {
"allow": [
"Bash(npm *)",
"Bash(git status)",
"Bash(git diff *)",
"Bash(git log *)",
"Read(**)"
],
"deny": [
"Bash(git push *)",
"Bash(git reset --hard *)",
"Bash(rm -rf *)",
"Write(.env*)",
"Write(**/*.key)",
"Write(**/*.pem)"
]
}
}
Personal overrides (developer preferences) go in .claude/settings.local.json — this file should be in .gitignore.
CI/CD Security Checklist
- Use a dedicated API key for CI — never reuse your personal key
- Store the API key in your CI secrets store (GitHub Actions secrets, etc.)
- Run Claude Code as a non-root user
- Use explicit allowlists — only allow the commands CI actually needs
- Add deny rules for all destructive operations
- Use
--printflag for non-interactive execution - Review Claude Code's output before using it in downstream steps
- Consider containerising for untrusted or third-party code analysis
Frequently Asked Questions
Can Claude Code delete my files?
In default interactive mode, any rm command requires your explicit approval — you see what it wants to run and choose to allow or deny. To automate this protection, add Bash(rm *) to your deny list. Claude Code will not silently delete files without you seeing what command it wants to run.
What happens if Claude runs a command I didn't expect?
In interactive mode, you see every command before it runs. Deny it if you don't want it to proceed. If you're in auto-approve mode and something unexpected happened, check your shell history (history | grep -v git) and review what was changed with git diff and git status.
Is it safe to use Claude Code on a machine with database credentials?
Yes, with precautions. Add deny rules for your credentials files: Write(~/.pgpass), Write(~/.my.cnf), Write(.env*). Claude Code will not write to those files. For read protection, add them to a read denylist too. Use environment variables for credentials, not files, where possible.
Can I audit what Claude Code has done?
Yes. Every command Claude Code runs appears in your shell history. Every file it edits shows in git diff. If you want a structured audit trail, add a hook that logs every Bash call: {"event": "PreToolUse", "matcher": "Bash", "hooks": [{"type": "command", "command": "echo \"[$(date)] CLAUDE_BASH: $CLAUDE_TOOL_INPUT\" >> ~/claude-audit.log"}]}.
→ Project Setup — CLAUDE.md and settings.json
→ Hooks — automate and restrict actions
→ Settings Reference — all settings.json options