Skip to content
KoishiAI
ไทย
← Back to contents
Chapter 11 / 12 · September 5, 2026

Permissions, Sandboxing and Security

All six permission modes and which one your sessions actually start in, the rule syntax that quietly opens more than you meant, the OS-enforced Bash sandbox, and what no mode ever auto-approves.

This guide is All Rights Reserved — free to read, copying/republication requires permission.

Chapter 11 | Permissions, Sandboxing and Security Written for: everyone who lets Claude Code run commands on their own machine

Three layers get muddled together constantly. Separate them first:

LayerAnswers
Permission modeDoes Claude ask you before acting?
Permission rules (allow / ask / deny)Is this tool or command allowed at all?
SandboxOnce a command is running, what can it reach?

The official documentation states the relationship plainly: “Permission modes decide whether Claude asks before an action, and the Bash sandbox and outer isolation boundaries decide what an action can reach once it runs.”


11.1 The six permission modes

Config valueLabel on screenRuns without askingSuits
defaultManualReads onlySensitive work, unfamiliar code
acceptEditsEdit automaticallyReads, file edits, and common filesystem commands (mkdir, touch, mv, cp)Iterating on code you are reviewing
planPlanReads, plus classifier-approved commands when auto mode is availableExploring a codebase before changing it
autoAutoEverything, with background safety checksLong tasks, less prompt fatigue
dontAskDon’t askOnly pre-approved toolsLocked-down CI and scripts
bypassPermissionsBypass permissionsEverythingIsolated containers and VMs only

The most confusing part: the mode that reviews everything is called Manual on screen, but its config value is default. The CLI accepts manual as an alias (v2.1.200 or later).

Which mode your session starts in

This is where the previous edition of this guide was out of date. On the Pro, Max and Team plans the built-in starting mode is auto mode, not Manual.

The order of precedence is:

  1. The --permission-mode flag, or --dangerously-skip-permissions
  2. permissions.defaultMode in a settings file
  3. The built-in default

And the built-in default depends on how you are running. The first row that matches applies:

CaseStarting mode
Any settings file sets disableAutoMode to "disable"default
Feature-flag fetching is offdefault
Your first session after an install or upgradedefault
claude -p or the Agent SDKdefault
Amazon Bedrock, Google Cloud’s Agent Platform, Microsoft Foundry, Claude Platform on AWSdefault
A Pro, Max or Team plan, in a terminal or the VS Code extensionauto
An Enterprise plan or a Claude Console API keydefault

There is one hidden trap: setting "auto" or "bypassPermissions" in .claude/settings.json or .claude/settings.local.json has no effect. In the bypassPermissions case the session starts in Manual instead. Other values work from any settings file.

Switching mid-session

In the CLI, press Shift+Tab to cycle. From auto, the first press goes to default, then the cycle runs defaultacceptEditsplan → back to default. The status bar shows the active mode, such as ⏸ manual mode on or ⏵⏵ auto mode on.

In VS Code click the mode indicator beneath the prompt box; in the desktop app use the selector next to the send button. The JetBrains plugin runs the CLI in the IDE terminal, so Shift+Tab works there too.

What no mode ever auto-approves

Including bypassPermissions. This list is worth memorising:

  • Tools matched by an explicit ask rule you wrote
  • Connector tools your organisation set to ask
  • Tools requiring a person: the built-in AskUserQuestion, and MCP tools marked requiresUserInteraction
  • rm and rmdir aimed at a critical path, which no allow rule and no hook "allow" can approve
  • The cross-session messaging safeguards

And deny rules block in every mode, bypassPermissions included. Allow rules, by contrast, have no effect in bypassPermissions.

When to use --dangerously-skip-permissions

The short answer: only inside a container or VM that is already isolated, and on Linux and macOS, running as a non-root user.

claude -p "<prompt>" --dangerously-skip-permissions

In such a -p run, the few calls that would still prompt are denied rather than allowed through.


11.2 Permission rules — the syntax that bites

{
  "permissions": {
    "defaultMode": "default",
    "allow": ["Bash(npm run *)", "Read(src/**)", "WebFetch(domain:github.com)"],
    "ask": ["Bash(git push *)"],
    "deny": ["Read(./.env)"],
    "additionalDirectories": ["/tmp/work"]
  }
}

Evaluation runs deny, then ask, then allow, and the first match in that order decides. Rule specificity does not change the order, so a broad deny like Bash(aws *) blocks everything matching it, including calls that also match a narrow allow like Bash(aws s3 ls).

The space before the asterisk

The most common mistake there is:

Written asWhat you get
Bash(git diff *)Commands beginning with git diff
Bash(git diff*)Also catches git diff-index, unintentionally
Bash(git *)Every git command, which is probably wider than you meant

An asterisk placed before the subcommand, as in Bash(git * main), is a risky form, because it also covers things like git -c core.fsmonitor=<script> diff main. Claude Code warns at startup when it finds an allow rule shaped like that.

Path depth means different things in allow and deny

WrittenIn a deny ruleIn an allow rule
Edit(src/**)Blocks both src/ and vendor/pkg/src/Allows only src/ beneath the working directory
Edit(**/src/**)Allows any src/ at any depth

Put simply: deny rules reach wide by default, allow rules reach narrow. That is the safe default, but it surprises people when an allow rule does not behave as expected.

Other forms in common use

"WebFetch(domain:example.com)"
"WebFetch(domain:*.example.com)"
"mcp__puppeteer"
"mcp__puppeteer__puppeteer_navigate"
"Agent(Explore)"

11.3 The Bash sandbox

This is entirely absent from the previous edition of this guide, and it is a different kind of layer from permission rules, because the operating system enforces it, not Claude Code.

It supports macOS, Linux and WSL2. Native Windows is not supported — run Claude Code inside WSL2 there. On macOS there is nothing to install; it uses the built-in Seatbelt framework. Linux and WSL2 need two extra packages.

Turn it on by typing /sandbox in a session — the panel tells you what is missing — or set sandbox.enabled to true in a settings file.

Two modes

Auto-allow: commands that can be sandboxed run and are approved automatically. Commands that cannot — those needing a host outside the allowlist, for instance — fall back to the regular permission flow.

Regular permissions: every Bash command goes through the normal flow, sandboxed or not.

The subtlety few people know: auto-allow works independently of your permission mode. Bash commands that modify files inside the sandbox boundary run without prompting even in Manual mode, where the file-editing tools would have asked. The exception is plan mode, where auto-allow does not widen approvals.

Even in auto-allow, deny rules still hold, ask rules naming a command such as Bash(git push *) still force a prompt, and rm/rmdir aimed at a critical path still goes through the normal flow.

Files — what can be written where

Scope
WritableThe working directory and below, anything added via --add-dir or permissions.additionalDirectories, and the session temp directory $TMPDIR points at
ReadableThe entire computer, except specifically denied directories
Not writableEverything else, including ~/.bashrc and system binaries in /bin/

Read that twice. By default the sandbox can still read credential files such as ~/.aws/credentials and ~/.ssh/. To stop it, configure sandbox.credentials or add those paths to denyRead yourself. The sandbox is primarily about blocking writes; it does not close off reads for you.

Paths protected even inside the writable zone

The reasoning is direct: a command able to edit these files could grant itself permissions, or add a hook or MCP server that Claude Code then runs outside the sandbox.

The protected set covers the .claude settings files and the skills, agents, commands and hooks directories beneath them, .mcp.json, the files Claude Code runs on its own, shell startup files such as .bashrc and .zshrc, .gitconfig, the .vscode and .idea directories, hooks and config inside .git, and most of ~/.claude.

There is no way to exempt one of these individually. An allowWrite entry or an Edit allow rule covering the path does not lift the protection. The only way to turn it off is filesystem.disabled, which switches off filesystem isolation for every path at once.

The network

By default no domain is allowed. The first time a command needs a new one, Claude Code prompts (or sends it to the classifier in auto mode). Answering Yes allows that host for the session; “Yes, and don’t ask again” saves a WebFetch(domain:...) rule to your local settings.

Pre-allow them to avoid the prompt:

{
  "sandbox": {
    "enabled": true,
    "network": {
      "allowedDomains": ["github.com", "*.npmjs.org"],
      "deniedDomains": ["evil.example.com"],
      "strictAllowlist": true
    }
  }
}

strictAllowlist denies instead of prompting — but setting it in a repository’s .claude/settings.json or .claude/settings.local.json has no effect. It must come from user settings, managed settings, or --settings.

Domain wildcards support two forms only: a leading *. and a bare *. A wildcard anywhere else, such as domain:example.*, still matches WebFetch but has no effect on sandboxed commands.

If your organisation uses a proxy, set HTTPS_PROXY, HTTP_PROXY and NO_PROXY in the env block of your settings, not just in your shell, so background agents inherit them.

The escape hatch when a command cannot be sandboxed

Claude Code reports which path or host the sandbox denied, and Claude may retry with the dangerouslyDisableSandbox parameter, which runs outside the sandbox and goes through the regular permission flow.

To be prompted every time, even in auto mode, add an ask rule:

"ask": ["Bash(dangerouslyDisableSandbox:true)"]

To close the hatch entirely, set "allowUnsandboxedCommands": false. The /sandbox panel calls this Strict sandbox mode.


11.4 Enforcement across an organisation

The managed settings file lives at:

OSPath
macOS/Library/Application Support/ClaudeCode/managed-settings.json
Linux and WSL/etc/claude-code/managed-settings.json
WindowsC:\Program Files\ClaudeCode\managed-settings.json

Claude Code no longer reads the legacy Windows path C:\ProgramData\ClaudeCode\managed-settings.json.

When several teams own different parts of a policy, split them into files under managed-settings.d/ beside managed-settings.json in the same system directory, rather than editing one shared file.

Settings an administrator can genuinely enforce include permissions.defaultMode, permissions.disableAutoMode set to "disable" to remove auto mode from the cycle so nobody can pick it, deny rules, and sandbox.network.allowManagedDomainsOnly, which blocks non-listed domains outright rather than prompting and honours only the entries from managed settings.


You wantStart withIsolation required
To review every action yourselfclaude --permission-mode defaultNone
Fewer prompts without a classifierManual plus the sandbox in auto-allow modeThe built-in sandbox (macOS/Linux/WSL2)
To explore before changing anythingclaude --permission-mode planNone
Long hands-off workclaude --permission-mode autoNone, though a sandbox adds depth
CI with an exact allowlistclaude -p "..." --permission-mode dontAsk --allowedTools "Bash(npm test)" "Read"Whatever your runner provides
Fully unattendedclaude -p "..." --dangerously-skip-permissionsRequired: a container or VM

What this chapter settles

The mode answers whether Claude asks, the rules answer whether it is allowed, the sandbox answers what it can reach. The three work independently, and opening one does not close another. The two facts most worth remembering: deny rules block in every mode, bypass included, and the sandbox is about blocking writes — it does not close off reads of your credential files by itself.

Glossary for this chapter

TermMeaning
Manual modeThe mode that asks before nearly everything; its config value is default
ClassifierThe second model that reviews actions on your behalf in auto mode
Protected pathsPaths the sandbox refuses to write, even inside the writable zone
Auto-allowThe sandbox mode that approves sandboxable commands itself
Strict sandbox modeClosing the dangerouslyDisableSandbox escape hatch
Managed settingsThe organisation’s policy file, overriding every other level