10 Claude Code Security Settings Every Developer Should Configure
Claude Code is the most capable coding agent I've used, but the same thing that makes it powerful (shell access, file I/O, network calls) is what makes a misconfigured setup dangerous. A stray rm -rf, a leaked .env, or a prompt-injection payload that quietly exfiltrates data to a random domain. These are all real risks when you run an agent on autopilot.
Below is the checklist I run through on every new machine and every new project. It's ordered by impact: do the first four and you've covered most of the blast radius.
1. Turn on the sandbox
The sandbox isolates Claude's Bash commands at the OS level (Seatbelt on macOS, Bubblewrap on Linux). This is the single biggest win.
// .claude/settings.json
{
"sandbox": {
"enabled": true
}
}
Check it's actually active with /sandbox inside a session.
2. Close the sandbox escape hatch
By default, Claude can escalate specific commands out of the sandbox. Disable that unless you have a reason to keep it open.
{
"sandbox": {
"enabled": true,
"allowUnsandboxedCommands": false
}
}
3. Deny dangerous commands explicitly
Permission rules evaluate in the order deny → ask → allow, so deny is your hard stop. Use it for the commands you never want Claude to run unsupervised.
{
"permissions": {
"deny": [
"Bash(rm -rf *)",
"Bash(git push --force *)",
"Bash(chmod 777 *)",
"Bash(curl * | sh)"
]
}
}
Even when a command is blocked by default, adding it to deny keeps a stray project-level allow from overriding it.
4. Block reads of secrets
This one catches me constantly: an agent helpfully cats an .env file while "debugging" and suddenly your OpenAI key is in the transcript.
{
"permissions": {
"deny": [
"Read(./.env)",
"Read(./.env.*)",
"Read(./secrets/**)",
"Read(**/*.pem)",
"Read(**/*.key)"
]
},
"sandbox": {
"filesystem": {
"denyRead": ["~/.aws/credentials", "~/.ssh"]
}
}
}
The sandbox-level denyRead matters because it stops Bash-side reads too, not just the Read tool.
5. Put network access on an allowlist
A malicious instruction hidden in a README or a scraped page can tell an agent to POST your codebase to an attacker's server. The fix is to flip the default from "allow all" to "allow only what I listed."
{
"sandbox": {
"network": {
"allowedDomains": [
"github.com",
"*.githubusercontent.com",
"registry.npmjs.org",
"pypi.org"
]
}
}
}
Start narrow. Add domains as real workflows demand them.
6. Kill bypass mode
--dangerously-skip-permissions is useful inside a fully-isolated container. On a regular dev machine, it should not be reachable.
{
"permissions": {
"disableBypassPermissionsMode": "disable"
}
}
For teams, push this through Managed Settings (see #10) so individuals can't turn it back on.
7. Use a PreToolUse hook for custom checks
Hooks run your own script at lifecycle points. A PreToolUse hook on Bash is the cleanest place to enforce project-specific rules that don't fit into a glob pattern.
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{ "type": "command", "command": ".claude/hooks/guard.sh" }
]
}
]
}
}
#!/bin/bash
# .claude/hooks/guard.sh
cmd=$(jq -r '.tool_input.command' < /dev/stdin)
if echo "$cmd" | grep -qE '(production|prod-db|DROP TABLE)'; then
echo "Blocked: production/destructive command" >&2
exit 2
fi
exit 0
Exit code 2 tells Claude the tool call is denied and surfaces the message back to the model so it can adjust.
8. Audit permissions regularly
"Always allow" drift is real. Every time you click through a prompt in a hurry, a rule gets added. Run /permissions every week or two and prune anything you don't recognize. /status tells you which settings files are actually loaded, which is invaluable when a rule isn't behaving.
9. Run inside a devcontainer for untrusted work
When I'm pointing Claude at a repo I don't fully trust, or letting it run on autopilot overnight, I do it in a container. Anthropic ships a reference devcontainer that includes a firewalled network and full host isolation.
git clone https://github.com/anthropics/claude-code.git
# Open in VS Code, "Reopen in Container"
Inside that environment, --dangerously-skip-permissions becomes a reasonable tradeoff rather than a footgun.
10. Teams: enforce it with Managed Settings
Individual discipline doesn't scale to ten engineers. Managed Settings sit at the top of the precedence chain. Users and projects cannot override them.
{
"permissions": {
"disableBypassPermissionsMode": "disable"
},
"allowManagedPermissionRulesOnly": true,
"allowManagedHooksOnly": true,
"allowManagedMcpServersOnly": true,
"sandbox": {
"enabled": true,
"allowUnsandboxedCommands": false,
"network": {
"allowManagedDomainsOnly": true,
"allowedDomains": ["github.com", "registry.npmjs.org"]
}
}
}
Deploy via MDM (Jamf, Intune) to the OS-specific managed-settings path, or use server-managed settings on Teams/Enterprise plans to push config at sign-in without touching endpoints.
Where to start
If you do nothing else this week, do steps 1 through 4. Sandbox on, escape hatch off, dangerous commands denied, secrets unreadable. That's the 80/20. Add the network allowlist the next time you're tempted to let Claude run unattended, and layer on hooks and Managed Settings as your setup matures.
The agent is only as safe as the walls you build around it.