Permissions Module
30 files · ~20K lines5 Layers Between You and Disaster — permission modes, rule matching, filesystem allowlists, and the yoloClassifier: an AI that asks AI whether a bash command is safe.
The 5-Layer Security Funnel
Every tool call passes through 5 narrowing layers. Each layer is more specific and can veto the call. Most calls are stopped before reaching layer 5.
Layer 1: Is the session in default, acceptEdits, or bypassPermissions mode? Mode determines whether a dialog is shown at all.
Layer 2: Has the user already approved this tool/command pattern in this session? Stored as PermissionRule objects in LoopState.
Layer 3: bashParser.ts builds a Tree-sitter AST of the command. Pattern classifier detects recursive deletes, root path access, network calls, injection chains.
Layer 4: File paths are validated against the project root allowlist. Paths outside allowed roots are blocked — even in bypassPermissions mode.
Layer 5: A terminal dialog renders in the REPL: Allow once / Always allow / Never. The user decides. 'Always allow' stores a new PermissionRule in session state.
Hall of Fame: Best Variable Names in Production Code
There is a function in production Claude Code literally called yoloClassifier. Here's what it actually does.
yoloClassifierutils/permissions/yoloClassifier.ts · ~8KBWhen Claude Code runs headlessly (CI mode, --dangerously-skip-permissions), it can't ask a human for permission. Instead, yoloClassifier sends the bash command to the Claude API with a safety assessment prompt. Claude-asking-Claude decides if it's safe. The name is literally in the source code.
bash command stringClaude API safety assessmentallow / block + reasonPermission Modes — Risk Spectrum
6 modes from safest to most dangerous. Each removes one or more security layers.
defaultNormal mode — all 5 layers active. User dialogs shown for every novel tool action.
acceptEditsAuto-approves file edits. Still prompts for bash commands, network, and destructive ops.
autoAcceptAccepts most tool calls automatically. Skips session-rule layer. Destructive ops still prompt.
planPlanning mode — Claude describes actions but doesn't execute them without explicit approval.
bypassPermissionsSkips user dialogs. yoloClassifier still runs. Path allowlist still enforced. Intended for CI pipelines.
dangerouslySkipPermissionsAll permission checks disabled. No classifier. No path check. Only use in fully sandboxed environments.
rm -rf / Walkthrough — All 5 Layers
The LLM generates BashTool('rm -rf /'). Here is what happens before a single byte is deleted.
Is the session in default, acceptEdits, or bypassPermissions mode? Mode determines whether a dialog is shown at all.
Has the user already approved this tool/command pattern in this session? Stored as PermissionRule objects in LoopState.
bashParser.ts builds a Tree-sitter AST of the command. Pattern classifier detects recursive deletes, root path access, network calls, injection chains.
File paths are validated against the project root allowlist. Paths outside allowed roots are blocked — even in bypassPermissions mode.
A terminal dialog renders in the REPL: Allow once / Always allow / Never. The user decides. 'Always allow' stores a new PermissionRule in session state.
Permission Rule Matching — 4 Types
When a user clicks 'Always allow', a rule is stored. Future calls match against these rules in priority order.
git commit -m 'fix'Full string equality. Fastest check.
git commitMatches if the command starts with this string. Covers variants like git commit -am, git commit --amend.
git *Shell glob patterns. * matches any sequence. Covers git pull, git push, git rebase, etc.
FileEdit:src/**Tool name + path glob. Approves FileEdit for any path under src/, but not outside it.
3 Security Vulnerabilities Patched (HackerOne)
Real vulnerabilities found and patched in production. The permission system was hardened after responsible disclosure.
A symlink inside the allowed root could point outside it. The fix: resolve real paths via fs.realpath() before allowlist comparison.
Malicious MCP server tool descriptions could inject instructions to the LLM. The fix: sanitize tool descriptions before they enter the system prompt.
Unicode lookalike characters in file paths could fool exact/prefix matching. The fix: normalize paths to NFC before rule comparison.
Key Files
utils/permissions/yoloClassifier.ts~8KBML classifier that uses AI to auto-approve bash commands — literally named 'yolo'
hooks/toolPermission/~12KBReact hooks for tool approval UI — renders permission dialogs in terminal
utils/permissions/~25KBPermission rule parsing, filesystem path allowlists, mode definitions
utils/permissions/pathPermissions.ts~6KBFilesystem path checks — resolves globs, validates against allowed roots
utils/permissions/permissionRules.ts~5KBPermission rule DSL: tool name patterns, command patterns, path patterns
Every tool calls checkPermissions() before invoke(). BashTool passes through all 5 layers above.
yoloClassifier and permission rules live in utils/permissions/ — part of the Utils module.
The main site's full permissions analysis including live examples and the full mode reference.