The default is closed, not open
Claude Code runs with access to your files, your shell, and often whatever credentials your shell can already reach. The reasonable worry about a coding agent is that it might, at some point, run something you didn’t intend. Anthropic’s own documentation is specific about how narrow the out-of-the-box behavior actually is: read-only tools such as file reads and search run without a prompt inside the working directory, editing a file requires approval every single time, and Bash commands require approval too, with one carve-out for a built-in list of read-only shell commands such as ls, cat, pwd, grep, and read-only forms of git [1]. Nothing in that default lets Claude Code touch a file or run an arbitrary command silently. Something has to change first.
What’s easy to miss is where that default is enforced. It is Claude Code’s own permission layer that decides whether a tool call proceeds — not the model, and not the instructions you write into a project’s CLAUDE.md file. Those instructions shape what Claude tries to do; they carry no authority to grant or revoke a capability. Only permission rules, a permission mode, or a hook running ahead of a tool call actually decide that [1]. That distinction matters because a lot of informal “guardrails” people write into project instructions are really just requests, and a confused agent, or one acting on text injected into a file it just read, can simply not follow one.
Allow, ask, and deny are not a spectrum
The permission system is built from three kinds of rule — allow, ask, and deny — layered across settings files at the managed, project, and user level. When more than one rule matches a tool call, Claude Code resolves the conflict in a fixed order: deny first, then ask, then allow, and rule specificity never changes that order [1]. A broad deny rule beats a narrower allow rule for the same command every time, and a bare deny on a tool name removes that tool from the model’s context entirely, so Claude never even attempts to call it. That fixed precedence is what makes centrally managed policy actually enforceable: a deny rule set by an organization cannot be quietly overridden by a more specific rule a developer adds later [2].
The precedence is simple enough to state directly. For a tool call
An unmatched command does not fail open into silent execution. It falls through to a prompt — what the documentation calls fail-closed matching [2].
What “auto-accept” changes, and what it doesn’t
“Auto-accept” is not one setting; it names several modes that trade away different amounts of oversight. acceptEdits mode auto-approves file edits and a fixed set of filesystem commands such as mkdir, touch, mv, and cp inside the working directory — an arbitrary shell command still prompts [1]. auto mode goes further and approves most tool calls automatically, backed by a two-stage classifier that screens each action before it runs: a fast filter tuned to err toward blocking, and a slower reasoning pass for anything the filter flags [3]. bypassPermissions — the mode behind the --dangerously-skip-permissions flag some developers call “YOLO mode” — skips essentially every prompt, with a short list of exceptions: explicit ask rules still fire, and a command that would wipe a filesystem root or a home directory still triggers a prompt as a last circuit breaker [1]. Anthropic’s own guidance is blunt about where that mode belongs: only inside an isolated container or VM where Claude Code cannot cause real damage [2].
Auto mode exists because the manual alternative doesn’t hold up under its own weight in practice. Anthropic reports that users accept roughly 93 percent of permission prompts anyway, which looks a lot more like habit than judgment [3]. But the classifier that replaces manual review isn’t error-free either: tested against a sample of real “overeager” agent actions, the two-stage classifier still missed 17 percent of them — mostly cases where it correctly flagged something as risky but misjudged whether the user’s actual request covered that specific action. Anthropic states plainly that auto mode is not a substitute for careful human review on high-stakes infrastructure [3].
File edits and shell commands are not the same risk
It’s tempting to treat “file access” and “command access” as one dial, but they behave differently in ways that matter operationally. A file-edit approval lasts only until the session ends; a Bash approval, once you answer “don’t ask again,” is written to a settings file and applies to that exact command in that repository permanently, across future sessions [1]. Edits are also bounded to tools Claude Code itself controls: a deny rule on a path blocks the Edit and Write tools there outright, full stop. A shell command has no equivalent ceiling. The documentation is direct about the gap: permission rules on file paths apply to Claude’s built-in tools and to file operations it recognizes inside Bash, but “they don’t apply to arbitrary subprocesses that read or write files indirectly, like a Python or Node script that opens files itself” [1]. Closing that gap requires the separate, OS-level sandbox, not a permission rule.
Bash is also where a naive configuration breaks first. Anthropic’s own docs warn that a pattern like Bash(curl http://github.com/ *), written with the intent of restricting network access to one domain, is defeated by an extra flag, a different protocol, a redirect, or a shell variable holding the real URL [1]. A rule that reads like a boundary on paper is not actually one unless it’s backed by sandbox network isolation or a validating hook, and network commands such as curl and wget are not auto-approved by default precisely because a Bash allow rule is such a weak place to enforce a domain restriction [2].
Where the real damage happens
None of this matters in the abstract; it matters because of what a coding agent is positioned to do once its permissions are loosened past what a task actually needs. Independent security researcher Simon Willison’s “lethal trifecta” names the combination that turns a permission mistake into a data breach: an agent with access to private data, exposed to content it didn’t write itself, and able to communicate externally sits in a position where one instruction hidden in that content can walk it through exfiltrating whatever it can read [4]. A Claude Code session with broad file-read access, a Bash allow rule wide enough to run curl, and exposure to an untrusted dependency, issue, or pull-request comment satisfies all three legs of that trifecta at once. A security review of the tool by application-security firm Checkmarx lists six risk categories that map almost directly onto permission configuration: weak approval governance, prompt injection, supply-chain compromise, data exfiltration, uncontrolled command execution, and inadvertent exposure of secrets in logs or generated output [5]. Every one of those is a permission-model failure before it is anything else — a rule too broad, a mode too permissive, or a boundary that was assumed rather than actually configured.
What to actually check
The practical version of all this is short enough to hold in your head. Know which mode a session is running in, and never leave bypassPermissions set outside a disposable container or VM. Treat “don’t ask again” on a Bash command as a permanent grant scoped to that exact repository, not a one-time convenience — it will still be in force months later. Write path-scoped deny rules for anything genuinely sensitive, and remember that they stop Claude’s own file tools, not a subprocess it launches; a real filesystem boundary needs the sandbox, not a permission rule alone. Don’t trust a Bash allow pattern to constrain a URL or an argument; use the WebFetch domain allowlist, sandbox network isolation, or a hook instead. And read CLAUDE.md instructions for what they are — guidance the model tries to follow, not the mechanism that actually enforces anything [1, 2]. The permission model is not a single switch between “safe” and “fast.” It is a stack of separately configured gates, and each one fails in its own specific way when someone assumes it covers more than it does.