A Claude Code agent does not have to be malicious to cause damage. It only has to be allowed to do the wrong thing.
That is the uncomfortable part of agent permissions. The scary failure is not always some sci-fi jailbreak. Sometimes it is a Bash tool with too much filesystem access, a reviewer clicking approve without reading, or a workflow that treats acceptEdits as a magic safety blanket.
The agent can be competent and the system can still be unsafe.
If you are moving Claude Code from experiments into team workflows, read the permissions model before you tune the prompt. Then read it again.
Permission mode is not a security strategy
Claude Code gives you broad permission modes, but the mode is only the top layer.
allowEdits means the agent can modify state without stopping for you. That can be useful in a sandboxed repo or a disposable workspace. It is a bad default when the agent can touch production-like files, secrets, deploy scripts, or customer data.
acceptEdits feels safer because the agent proposes changes before it executes them. It is only safer if a human actually reads the proposal. If the review step becomes a reflex click, you have built slow allowEdits with better theatre.
askPerAction gives you the most human oversight, but it also burns attention. If a workflow needs dozens of approvals, people will either stop using it or start rubber-stamping. Neither outcome is a control.
The mode you choose is really a bandwidth decision: how much human judgment can this workflow afford, and where should that judgment happen?
Per-tool permissions are where the real risk lives
The global mode is coarse. The dangerous details usually live at the tool level.
A Bash tool with path limits is a very different thing from Bash with full repo access. A network tool restricted to one vendor API is different from a network tool that can call anything. A file writer locked to /tmp/agent-output is different from one that can update configs, scripts, and deployment manifests.
Before giving Claude Code a tool, ask four questions:
- What can this tool read?
- What can it write or delete?
- What network can it reach?
- What happens if the model uses it correctly, but in the wrong place?
That last question matters. A well-formed command against the wrong path can still ruin your evening.
Default-deny beats cleanup
A production Claude Code setup should start from default-deny.
Do not hand the agent broad access and promise to watch it carefully. Give it the smallest workspace that lets the job complete. Add blocked paths for sensitive directories. Turn off network access unless the workflow needs it. If it needs network access, whitelist domains rather than trusting the model to stay polite.
This sounds slow. It is slower than a demo. It is also much faster than explaining after an incident why the agent could write to places it never needed.
A useful rollout pattern:
- Run the workflow in
askPerActionwhile designing it. - Record the actions that are repeatedly safe and necessary.
- Convert those actions into explicit per-tool permissions.
- Move only the low-risk repeat path to
acceptEditsorallowEdits. - Keep anything unusual behind a human review gate.
You are not trying to remove all human review. You are trying to spend review where it actually changes the outcome.
The permission audit you want before a regulator asks
If an agent touches regulated, customer-facing, or money-adjacent systems, you need an answer to a simple question: what was the agent allowed to do at the time?
Not what you intended. Not what the README says now. What was true when the session ran.
Keep a small permission record with each production run:
- permission mode
- tool list
- per-tool read and write scopes
- network allowlist
- blocked paths
- reviewer identity for approved actions
- session ID or trace ID
- code/config version
This is boring metadata until the day you need it. Then it is the difference between a contained incident and a week of archaeology.
The practical test before production
Before putting a Claude Code workflow near production data, run this test:
- Can the agent write outside the intended workspace?
- Can it read secrets, tokens, SSH keys, or local config files?
- Can it call the public internet or internal network without a domain allowlist?
- Can it modify deploy scripts, CI files, or package manifests?
- Can a reviewer understand the proposed action quickly enough to make a real decision?
- Is every approved action tied to a session or audit record?
If the answer is “I think so,” you are not ready. If the answer is “we do not know,” you are definitely not ready.
I am writing these production patterns into a LeanPub book: Claude Code: Building Production Agents That Actually Work.
It is for engineers and architects who already know Claude Code can be powerful and now need to make it safe enough for real systems: permissions, hooks, MCP, evals, observability, cost controls, and human review.
Book draft: Claude Code: Building Production Agents That Actually Work