Skip to content

Commit de981f4

Browse files
committed
docs(gatekeeper): rewrite README with 3-tier architecture and all-tool coverage
1 parent c38052a commit de981f4

1 file changed

Lines changed: 120 additions & 26 deletions

File tree

plugins/gatekeeper/README.md

Lines changed: 120 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,128 @@
11
# Gatekeeper Plugin
22

3-
Two-layer security for Claude Code: auto-approve safe commands, AI-assisted review for the rest.
3+
Three-tier security for Claude Code: auto-approve safe commands, block destructive ones, and AI-review everything in between — across all tools.
44

55
## Overview
66

7-
Gatekeeper eliminates repetitive permission dialogs for safe development commands while maintaining security against destructive operations.
7+
Gatekeeper eliminates repetitive permission dialogs for safe development commands while maintaining security against destructive operations. It covers **all Claude Code tools** (Bash, Write, Edit, WebFetch, and more), not just shell commands.
88

99
### How It Works
1010

1111
```text
12-
Bash command
12+
Any tool call (Bash, Write, Edit, WebFetch, Read, etc.)
1313
1414
1515
Layer 1: PreToolUse (pattern matching, <5ms)
16-
├── ALLOW: safe patterns (npm, git, node, etc.) → skip permission dialog
17-
├── DENY: destructive patterns (rm -rf /, mkfs, etc.) → block immediately
18-
└── PASSTHROUGH: unknown commands → permission dialog
19-
20-
21-
Layer 2: PermissionRequest (AI agent, opus)
22-
├── approve → execute
23-
└── reject → block with reason
16+
├── HARD DENY: destructive patterns → block immediately
17+
├── SOFT DENY: risky but sometimes intended → passthrough to AI
18+
├── ALLOW: safe patterns → skip permission dialog
19+
└── UNKNOWN: no matching rule → passthrough to AI
20+
21+
22+
Layer 2: PermissionRequest (AI agent, haiku)
23+
├── "Did user explicitly request this?"
24+
│ ├── Yes → allow
25+
│ └── No → deny with reason
26+
└── Unsure → user sees permission prompt
2427
```
2528

26-
## Allowed Patterns
29+
### Decision Types
30+
31+
| Decision | Hook Output | Effect |
32+
|----------|------------|--------|
33+
| **Hard Deny** | `{ permissionDecision: "deny" }` | Tool blocked immediately, stderr message |
34+
| **Soft Deny** | `null` (passthrough) | Proceeds to AI review in PermissionRequest |
35+
| **Allow** | `{ permissionDecision: "allow" }` | Tool executes, permission dialog skipped |
36+
| **Unknown** | `null` (passthrough) | Proceeds to AI review (fail-open) |
37+
38+
## Tool Coverage
39+
40+
### Bash Commands
41+
42+
#### Hard Deny (absolute blocks)
43+
44+
| Pattern | Reason |
45+
|---------|--------|
46+
| `rm -rf /` | Filesystem root deletion |
47+
| `rm -rf /*` | Destructive wildcard deletion from root |
48+
| `rm -rf ~` | Home directory deletion |
49+
| `mkfs.*` | Disk format |
50+
| `dd if=/dev/zero of=/dev/` | Disk zeroing |
51+
| `node -e`, `python -c`, etc. | Inline interpreter code execution |
52+
| `find -exec/-execdir/-delete` | Arbitrary command execution |
53+
54+
#### Soft Deny (AI reviews intent)
55+
56+
| Pattern | Reason |
57+
|---------|--------|
58+
| `git push --force` | Force push needs user intent verification |
59+
| `git push origin main` | Push to default branch needs user intent verification |
60+
| `git reset --hard` | Hard reset needs user intent verification |
61+
| `git clean -f` | Git clean needs user intent verification |
62+
| `git branch -D` | Force branch delete needs user intent verification |
63+
| `npm publish` | Package publish needs user intent verification |
64+
| `terraform apply/destroy` | Infrastructure change needs user intent verification |
65+
| `kubectl apply/delete` | Kubernetes mutation needs user intent verification |
66+
| `git commit --no-verify` | Skipping commit verification needs user intent verification |
67+
| `chmod 777` | Broad permission change needs user intent verification |
68+
| `nc -l`, `python -m http.server` | Exposing local service needs user intent verification |
69+
| `crontab`, `systemctl enable` | Unauthorized persistence needs user intent verification |
70+
| IAM/RBAC commands | Permission grant needs user intent verification |
71+
72+
#### Allowed (instant approve)
2773

2874
| Category | Examples |
2975
|----------|----------|
3076
| Package managers | `npm test`, `bun install`, `yarn add`, `pnpm run` |
3177
| Git read | `git status`, `git log`, `git diff`, `git branch` |
3278
| Git write | `git add`, `git commit`, `git merge`, `git pull` |
33-
| Git push | `git push` (non-force only) |
79+
| Git push | `git push` (non-force, non-main) |
3480
| Build/runtime | `node`, `npx`, `tsx`, `python`, `cargo build`, `make` |
3581
| File inspection | `ls`, `cat`, `grep`, `find`, `tree`, `wc` |
3682
| Docker read | `docker ps`, `docker logs`, `docker images` |
3783

38-
## Denied Patterns
84+
### Write/Edit
3985

40-
| Pattern | Reason |
41-
|---------|--------|
42-
| `rm -rf /` | Filesystem root deletion |
43-
| `rm -rf /*` | Destructive wildcard deletion from root |
44-
| `rm -rf ~` | Home directory deletion |
45-
| `mkfs.*` | Disk format |
46-
| `dd if=/dev/zero of=/dev/` | Disk zeroing |
86+
| Decision | Pattern | Reason |
87+
|----------|---------|--------|
88+
| Soft Deny | `.env`, `.env.*` | Secrets file |
89+
| Soft Deny | `.claude/settings` | Agent self-modification |
90+
| Soft Deny | `CLAUDE.md` | Agent self-modification |
91+
| Soft Deny | `.github/workflows/*` | CI/CD config |
92+
| Soft Deny | `.gitlab-ci.yml`, `Jenkinsfile`, `.circleci/*` | CI/CD config |
93+
| Allow | Project-relative paths | Safe project file |
94+
| Passthrough | Absolute paths outside project | AI review |
95+
96+
### WebFetch
97+
98+
| Decision | Pattern | Reason |
99+
|----------|---------|--------|
100+
| Soft Deny | Paste services (pastebin, hastebin, etc.) | Data exfiltration risk |
101+
| Soft Deny | File sharing (transfer.sh, file.io, etc.) | Data exfiltration risk |
102+
| Soft Deny | Script downloads (`.sh`, `.bash`, `.ps1`) | Code execution risk |
103+
| Allow | `localhost`, `127.0.0.1` | Safe dev server |
104+
| Passthrough | Other URLs | AI review |
105+
106+
### Safe Tools (instant allow)
107+
108+
Read, Glob, Grep, LS, Search, TaskCreate, TaskUpdate, TaskList, TaskGet, TodoRead, TodoWrite, NotebookRead
109+
110+
### Unknown Tools
111+
112+
All unrecognized tools pass through to the AI review layer (fail-open design).
113+
114+
## AI Review (Layer 2)
115+
116+
The PermissionRequest hook uses an AI agent (haiku model) with rules derived from [Claude Code's auto-mode classifier](https://www.anthropic.com/engineering/claude-code-auto-mode):
117+
118+
**Core principle**: "Did the user explicitly request this action?"
119+
120+
The AI prompt covers 7 ALLOW rules and 25+ DENY rules including:
121+
- Data exfiltration and credential exposure
122+
- Supply chain attacks and untrusted code integration
123+
- Infrastructure mutations and production access
124+
- Agent self-modification and unauthorized persistence
125+
- External system writes and content fabrication
47126

48127
## Installation
49128

@@ -64,19 +143,34 @@ bun run build
64143
### Testing
65144

66145
```bash
146+
bun test
147+
148+
# Manual tests:
149+
150+
# HARD DENY test
151+
echo '{"tool_name":"Bash","tool_input":{"command":"rm -rf /"}}' | node dist/pre-tool-use.js
152+
153+
# SOFT DENY test (no output = passthrough to AI)
154+
echo '{"tool_name":"Bash","tool_input":{"command":"git push --force"}}' | node dist/pre-tool-use.js
155+
67156
# ALLOW test
68157
echo '{"tool_name":"Bash","tool_input":{"command":"npm test"}}' | node dist/pre-tool-use.js
69158

70-
# DENY test
71-
echo '{"tool_name":"Bash","tool_input":{"command":"rm -rf /"}}' | node dist/pre-tool-use.js
159+
# Safe tool ALLOW test
160+
echo '{"tool_name":"Read","tool_input":{"file_path":"test.ts"}}' | node dist/pre-tool-use.js
161+
162+
# Write soft deny test (no output = passthrough to AI)
163+
echo '{"tool_name":"Write","tool_input":{"file_path":".env"}}' | node dist/pre-tool-use.js
72164

73-
# PASSTHROUGH test (no output)
74-
echo '{"tool_name":"Bash","tool_input":{"command":"curl https://example.com"}}' | node dist/pre-tool-use.js
165+
# PASSTHROUGH test (unknown tool, no output)
166+
echo '{"tool_name":"Agent","tool_input":{}}' | node dist/pre-tool-use.js
75167
```
76168

77169
## References
78170

79-
- [Claude Code Tips: PermissionRequest Hook Pattern](https://www.threads.com/@boris_cherny/post/DUMZy85EoFj)
171+
- [Anthropic: Claude Code Auto Mode](https://www.anthropic.com/engineering/claude-code-auto-mode)
172+
- [Anthropic: Claude Code Sandboxing](https://www.anthropic.com/engineering/claude-code-sandboxing)
173+
- [Claude Code Hooks Documentation](https://code.claude.com/docs/en/hooks)
80174

81175
## License
82176

0 commit comments

Comments
 (0)