Core System

Permission & Security

Three-layer defense-in-depth — powerful yet safe AI

~7 min read

0

Defense layers

0

Permission module files

0+

Security LOC

Claude Code can execute commands, modify files, and access the web. Powerful, but it could perform dangerous operations. The permission system is its safety lock — ensuring every action is vetted.

Think of it like three airport security checkpoints:

🔬 X-ray machine (ML classifier) — auto-scans, quickly passes safe items, blocks obvious threats 👮 Security officer (rule engine) — checks against regulations (your custom rules) ✋ Passenger confirmation (user dialog) — when in doubt, you decide

Three Layers of Defense #

Click a node to see how each layer works

evaluate
uncertain
no match
decide

Permission Simulator #

Pick a command, watch the three layers evaluate it

Permission Simulator — pick a command to see the three-layer evaluation

Bash Security Analysis #

How shell commands are parsed and analyzed

When Claude wants to run a shell command, the system doesn't just look at the text — it parses the command into an Abstract Syntax Tree (AST) like a compiler.

For example, `cat file.txt | grep secret > output.txt` is identified as: a pipeline that reads a file, filters content, then writes to another file. Each sub-command's risk level is analyzed for command injection and path traversal.

Rule System #

How users customize security policies

"allow": ["git *", "npm test"] Always allow git and npm test commands
"deny": ["rm -rf *", "sudo *"] Deny delete and sudo commands
CLI: --always-allow-bash CLI flag: allow all Bash commands (dangerous!)
"permissionMode": "auto" Auto mode: ML classifier makes all decisions

Core Code #

Simplified three-layer permission check

src/permissions.tsPermission Entry
Step 1 of 5
1// src/permissions.ts — Permission entry point
2export async function hasPermissionsToUseTool(
3 tool: Tool,
4 input: ToolInput,
5 context: PermissionContext
6): Promise<PermissionDecision> {
7 const decision = await (
8 tool, input, context
9 );
10
11 // Track consecutive denials for safety monitoring
12 if (decision.allowed) {
13 consecutiveDenials = 0;
14 } else {
15 consecutiveDenials++;
16 }
17
18 // In 'dontAsk' mode, convert 'ask' to 'deny'
19 if (context.permissionMode === "dontAsk"
20 && decision.behavior === "ask") {
21 return { allowed: false, reason: "dontAsk" };
22 }
23
24 return decision;
25}

Every tool call passes through hasPermissionsToUseTool(). It wraps the inner check with denial tracking — if a tool is allowed, consecutive denial counters reset. If denied in 'dontAsk' mode, 'ask' decisions are converted to 'deny' silently.

Click highlighted function names to follow the call chain

← → arrow keys to navigate