Dev.to Security 🔐 Cybersecurity 👁 0 📖 2 min read

Permissions & Tool Allowlisting in Claude Code: A Beginner's Guide

The Scenario Remember the setup from the first article — a project with CLAUDE.md, an api-conventions skill, and a code-reviewer subagent, all working together to keep new API endpoints consistent? Same project. But Cl

Permissions & Tool Allowlisting in Claude Code: A Beginner's Guide

The Scenario

Remember the setup from the first article — a project with CLAUDE.md, an api-conventions skill, and a code-reviewer subagent, all working together to keep new API endpoints consistent? Same project. But Claude Code doesn't only touch files — it can also run terminal commands and, if you've connected one, query your actual database.

So now picture this: mid-session, Claude decides the fix for a bug is to push the branch straight to remote before you've looked at it. Or it runs a "quick" database command to test something, and that command is a DROP. Nothing in the skill or the subagent stops either of those — they only cover how code should look and who reviews it. Neither one ever asked "should this specific action be allowed to happen at all?"

That question is what permissions answer.

Permission, in One Sentence

A permission is a gate: before Claude runs a tool call, a rule decides whether it's allowed, denied, or needs your OK first. It's not reasoning about risk — it's checking a pattern you wrote in advance.

manual approve vs permission rule

Three Outcomes

Every tool call lands in one of three buckets:

  • Allow → runs instantly, no prompt
  • Ask → pauses, waits for you to say yes
  • Deny → blocked, full stop

Back to the Scenario: One Real Example

Permission rules live in .claude/settings.json, right alongside the skill and subagent files from the first article:

your-project/
├── CLAUDE.md
├── .claude/
│   ├── settings.json          ← permission rules go here
│   ├── skills/
│   └── agents/
└── src/

Commit that file to the repo, and the project can share the same permission configuration across the team.

Here's a rule set that directly stops both close calls from the opening — one rule per tool, so you can see this isn't just a Bash thing:

{
  "permissions": {
    "allow": ["Bash(git *)"],
    "ask": ["Bash(git push *)"],
    "deny": ["Database(DROP *)"]
  }
}
  • git status, git diffallowed, they're harmless
  • git pushasks first — the more specific git push rule takes precedence over the broader git * rule
  • Any DROP query against the database, through whatever tool gives Claude that access → denied, no exceptions

Two different tools, same three-outcome idea. Once you understand the pattern, you can use the same allow/ask/deny idea across the tools Claude Code can use.

Claude asked for permission

📦 Full example: https://github.com/Alimurrazi/claude-demo-book-api/releases/tag/article-2-permissions — the repo as it stood for this article, including .claude/settings.json above.

The same rules aren't only useful for teams, either — they also protect you, three hours into a solo debugging session, from your own tired typo turning into a dropped table.

The Trade-off

More "ask" rules ≠ more safety. If Claude asks about everything, you stop reading the prompts and just click yes — and now the gate isn't protecting anything.

Permission only helps if someone actually reads it

A permission only helps if someone actually reads it.

Takeaways

  • Permission = a gate checked before a tool call runs, not a reasoning step.
  • Three outcomes — allow, ask, deny — and they apply across every tool Claude has, not just Bash.
  • A narrow, specific rule (like blocking just DROP on the database) can coexist with a broad allow on everything else.
  • Useful for trusting a teammate less and for catching your own mistakes.
📰 Read the original article on Dev.to Security

Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.