Claude Code Permissions and Sandboxing: How Much to Actually Let It Do

Anand B · 2026-08-08

The blast radius that matters is not your working tree. Git already protects that, and a bad edit costs you a git checkout. What nothing protects is the credential you handed the agent and the remotes it can reach with it.

Claude Code security discussions almost always start in the wrong place, arguing about whether the model might delete a file. Start instead with what the process can reach, because that is the part where a mistake is not recoverable with a git command.

Two layers that people mistake for one

Permissions and sandboxing are separate systems doing different jobs, and knowing which is which explains most surprising behaviour.

Permissions as an inner layer around Claude's decisions and the sandbox as an OS-level outer boundary
Deny rules govern what Claude decides to do. The sandbox governs what the OS lets happen.

Claude Code permissions constrain what the agent chooses to do. Sandboxing is OS-level enforcement of what the Bash tool and its child processes are physically able to touch.

The gap between them is sharp enough to be worth memorising. Read and Edit deny rules apply to the built-in file tools and to file commands Claude Code recognises in Bash, like cat, head, tail and sed. They do not apply to arbitrary subprocesses. A Python or Node script that opens a file itself sails straight past a deny rule, because the deny rule was never an OS control. If you need a path genuinely unreachable, you need the Claude Code sandbox, not a permission rule.

The two compose deliberately. Filesystem restrictions merge sandbox.filesystem settings with your Read and Edit deny rules, and network restrictions merge WebFetch permission rules with the sandbox's allowedDomains and deniedDomains. There is also a convenience worth knowing about: with autoAllowBashIfSandboxed at its default of true, sandboxed Bash commands run without prompting even if you have a bare Bash ask rule, because the sandbox boundary substitutes for that prompt.

The six modes, ranked by how much you are trusting

Shift+Tab cycles modes mid-session. What each one lets through:

ModeRuns without askingReasonable when
default / ManualReads onlyUnfamiliar repo, sensitive work
acceptEditsEdits plus mkdir, mv, cpYou are reading the diffs as they land
planReads, no source editsExploring before changing anything
autoEverything, classifier-checkedLong mechanical tasks
dontAskOnly pre-approved toolsLocked-down CI and scripts
bypassPermissionsEverythingContainers and VMs only

dontAsk is the underused one. It never prompts, but it also only runs what you pre-approved, which is exactly the right shape for CI: deterministic, silent, and incapable of surprising you. Reaching for bypassPermissions in a pipeline when you wanted dontAsk is a common and unnecessary risk.

What Claude Code yolo mode actually still refuses

--dangerously-skip-permissions is equivalent to --permission-mode bypassPermissions, and it is what people mean by Claude Code yolo mode. It disables prompts and safety checks, including writes to protected paths like .git, .claude, .vscode, .idea and .cargo.

Circuit breakers that still fire under bypassPermissions, including rm -rf and running as root
Even with checks off, five things still stop. None of them are a substitute for isolation.

It is not quite a blank cheque, and the exceptions are informative:

Those last two are the design worth copying: escalation happens at a boundary you crossed deliberately, not somewhere in the middle of a long session.

Decide what you are actually protecting

Concentric rings showing the working tree, the local machine, and credentials and remotes as the unprotected outer ring
Recoverability drops as you move outward. So does the amount of protection available.

Three rings, and only the inner two have real defences.

Your working tree is the innermost and the least worrying. Commit often and it is almost fully recoverable.

Your machine is next. A container, VM, or the sandbox handles this ring, and if you are running anything unattended or on an unfamiliar repository, this is the ring to actually address. bypassPermissions inside a network-isolated container is a coherent posture. bypassPermissions on your laptop is not a posture, it is a hope.

The outer ring is credentials, remotes and production, and nothing in the permission system meaningfully protects it. A token in the environment is usable by anything the agent runs, whether or not that thing is a tool Claude Code recognises. The mitigations here are unglamorous and they are the ones that matter: scope tokens narrowly, use short-lived credentials, keep production credentials out of any environment an agent runs in, and protect branches server-side so a git push cannot land on main regardless of what the agent decides. Note that auto mode already treats deploy-shaped branch names like production and gh-pages as special, which tells you Anthropic reached the same conclusion about where the danger is.

The threat you cannot prompt your way out of

Everything above assumes the risk is the model making a poor choice. The harder case is the model being told what to do by something that is not you.

An agent reads files, fetches pages, and pulls in issue text, dependency READMEs and tool output. Any of that content can contain instructions aimed at the agent. This is why the sandbox matters more than the permission mode: a permission rule constrains what Claude decides, and the whole point of an injection is to change what Claude decides. The sandbox does not care what the model was persuaded of, because it is enforced a layer below the persuasion.

Three practices follow, and none of them involve better prompting. Treat everything a tool returns as data rather than instruction, which is a property of how you configure the agent, not something you can ask it to remember. Keep the network allowlist tight, because exfiltration needs a destination and deniedDomains is cheaper than detection. And be specific about which directories are readable, since an agent that cannot read ~/.aws cannot be talked into sending you its contents.

The uncomfortable implication is that the more autonomy you grant, the more the untrusted content your agent consumes becomes part of your attack surface. That is an argument for isolation, not for a longer system prompt.

The multi-user case is a different problem

Once more than one person shares a session, permission modes stop being sufficient, because a mode is a property of the session rather than of the participant.

We build collaborative sessions, so this is from experience: the workable shape is that policy is enforced by the host rather than negotiated by clients, guests get a default role with the narrowest useful capability set, new joiners land in a waiting room instead of straight into the session, trust is tracked per guest, and sensitive actions are held for explicit approval. A guest-side setting that the host does not verify is decoration.

The rule that generalises: any control that lives on the client is a suggestion. If it matters, the host enforces it. The same logic explains a detail in Claude Code's own design — defaultMode: "auto" is honoured from ~/.claude/settings.json but deliberately ignored in a project's .claude/settings.json, so that cloning a repository cannot grant that repository elevated permissions on your machine. A repo is a client. It gets to suggest.

Two more places the same principle applies. Managed settings can set permissions.disableBypassPermissionsMode and permissions.disableAutoMode to "disable", which removes those modes from the Shift+Tab cycle and rejects the equivalent launch flags outright — an organisation-level control rather than a per-developer preference. And on Team or Enterprise plans an Owner has to enable auto mode before anyone can turn it on at all.

A posture worth copying

Manual or plan mode in an unfamiliar repository. acceptEdits while you are reading the diffs. auto for long mechanical work where the classifier's judgement is genuinely useful. dontAsk in CI. bypassPermissions only inside a container with no network path to anything you care about.

Then do the boring part, which is worth more than every mode above combined: audit what is in the environment your agent inherits. If a leaked token from that environment would be a bad afternoon, the permission mode is not your problem. If you are running several agents unattended, the gating rules for loops are the other half of this, because a scheduled mistake repeats and a manual one does not.

All posts · SpeakCode