claude-warden 2.0.1 → 2.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +78 -19
- package/config/warden.default.yaml +83 -31
- package/dist/codex-export.cjs +794 -298
- package/dist/index.cjs +799 -298
- package/package.json +2 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "warden",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.2",
|
|
4
4
|
"description": "Smart command safety filter for Claude Code — parses shell pipelines and evaluates per-command safety rules to auto-approve safe commands and block dangerous ones",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "banyudu"
|
package/README.md
CHANGED
|
@@ -42,6 +42,28 @@ The result: **100+ common dev commands auto-approved**, dangerous commands auto-
|
|
|
42
42
|
| `ssh devserver cat /etc/hosts` | Prompted | Auto-allowed (trusted host + safe cmd) |
|
|
43
43
|
| `ssh devserver sudo rm -rf /` | Prompted | Auto-denied (trusted host + dangerous cmd) |
|
|
44
44
|
|
|
45
|
+
## Warden vs Auto Mode
|
|
46
|
+
|
|
47
|
+
Claude Code recently introduced [Auto Mode](https://code.claude.com/docs/en/permission-modes#eliminate-prompts-with-auto-mode), which uses a background classifier model to approve or block actions without manual prompts. Here's how it compares to Warden:
|
|
48
|
+
|
|
49
|
+
| | Warden | Auto Mode |
|
|
50
|
+
|---|---|---|
|
|
51
|
+
| **How it works** | Deterministic rule engine with AST-based shell parsing | LLM classifier (Sonnet 4.6) reviews each action |
|
|
52
|
+
| **Availability** | All plans, all models, all providers (API, Bedrock, Vertex) | Team/Enterprise only, Sonnet 4.6 or Opus 4.6 only |
|
|
53
|
+
| **Token cost** | Zero — runs locally as a hook | Extra classifier calls count toward token usage |
|
|
54
|
+
| **Latency** | Near-instant (local process) | Network round-trip per classified action |
|
|
55
|
+
| **Configurability** | Full control via YAML — per-command rules, `targetPolicies`, and `trustedRemotes` | Prose-based rules, admin-managed trusted infrastructure |
|
|
56
|
+
| **Predictability** | Deterministic — same command always gets the same decision | Probabilistic — classifier may have false positives/negatives |
|
|
57
|
+
| **Scope** | Shell commands only (Bash tool) | All tool calls (Bash, file edits, network, subagents) |
|
|
58
|
+
|
|
59
|
+
**Can I use both?** Yes. Warden runs as a `PreToolUse` hook, which executes before Auto Mode's classifier. Warden handles fast, deterministic decisions for shell commands, and Auto Mode covers everything else (file edits, network requests, subagent spawning). They are complementary.
|
|
60
|
+
|
|
61
|
+
**When to choose Warden alone:** You're on a Free/Pro plan, using API/Bedrock/Vertex providers, want zero extra token cost, or need deterministic and auditable command-level rules.
|
|
62
|
+
|
|
63
|
+
**When to choose Auto Mode alone:** You want broader coverage beyond shell commands and are comfortable with classifier-based decisions.
|
|
64
|
+
|
|
65
|
+
**When to use both:** You want the best of both worlds — instant deterministic shell command filtering from Warden, plus Auto Mode's broader safety net for non-shell actions.
|
|
66
|
+
|
|
45
67
|
## Install
|
|
46
68
|
|
|
47
69
|
Two commands inside Claude Code:
|
|
@@ -129,17 +151,34 @@ alwaysAllow:
|
|
|
129
151
|
alwaysDeny:
|
|
130
152
|
- nc
|
|
131
153
|
|
|
132
|
-
# Trusted remote
|
|
133
|
-
|
|
134
|
-
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
-
|
|
139
|
-
|
|
140
|
-
-
|
|
141
|
-
|
|
142
|
-
-
|
|
154
|
+
# Trusted remote contexts (auto-allow connection, evaluate remote commands)
|
|
155
|
+
trustedRemotes:
|
|
156
|
+
- context: ssh
|
|
157
|
+
name: devserver
|
|
158
|
+
- context: ssh
|
|
159
|
+
name: "*.internal.company.com"
|
|
160
|
+
- context: docker
|
|
161
|
+
name: my-app
|
|
162
|
+
- context: docker
|
|
163
|
+
name: dev-*
|
|
164
|
+
- context: kubectl
|
|
165
|
+
name: minikube
|
|
166
|
+
- context: sprite
|
|
167
|
+
name: my-sprite
|
|
168
|
+
|
|
169
|
+
# Target-based policy overrides for data-sensitive commands
|
|
170
|
+
targetPolicies:
|
|
171
|
+
- type: path
|
|
172
|
+
path: "{{cwd}}"
|
|
173
|
+
commands: [rm, cp, mv]
|
|
174
|
+
decision: allow
|
|
175
|
+
- type: endpoint
|
|
176
|
+
pattern: "http://localhost:*"
|
|
177
|
+
decision: allow
|
|
178
|
+
- type: database
|
|
179
|
+
host: "prod-db.internal"
|
|
180
|
+
decision: deny
|
|
181
|
+
reason: Production database
|
|
143
182
|
|
|
144
183
|
# Per-command rules (override built-in defaults for this scope)
|
|
145
184
|
rules:
|
|
@@ -169,6 +208,17 @@ Need to temporarily bypass all permission prompts? YOLO mode auto-allows all com
|
|
|
169
208
|
|
|
170
209
|
Running `/warden:yolo` with no arguments shows a menu of duration options.
|
|
171
210
|
|
|
211
|
+
### Activate via environment variable
|
|
212
|
+
|
|
213
|
+
For non-interactive sessions where `/warden:yolo` can't be invoked (e.g. piped prompts), set the `WARDEN_YOLO` env var:
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
WARDEN_YOLO=true claude < prompts.txt
|
|
217
|
+
WARDEN_YOLO=1 claude < prompts.txt
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
Unlike the slash command, `WARDEN_YOLO` bypasses **all** checks including always-deny commands — it short-circuits before any parsing or evaluation, same as `--dangerously-skip-permissions`.
|
|
221
|
+
|
|
172
222
|
### How it works
|
|
173
223
|
|
|
174
224
|
YOLO mode is **session-scoped** — it only affects the current Claude Code session. The hook intercepts special activation commands and stores state in a temp file keyed by session ID. When a command is evaluated during YOLO mode, the hook skips normal rule evaluation and auto-allows (except always-deny commands). Expired YOLO states are cleaned up automatically.
|
|
@@ -200,21 +250,30 @@ Commands like `node`, `npx`, `docker`, `ssh`, `git push --force`, `rm`, `chmod`
|
|
|
200
250
|
- `rm temp.txt` is allowed but `rm -rf /` is prompted
|
|
201
251
|
- `chmod 644 file` prompts but `chmod -R 777 /var` is denied
|
|
202
252
|
|
|
203
|
-
### Trusted
|
|
204
|
-
Configure
|
|
205
|
-
- **SSH**: `
|
|
206
|
-
- **Docker**: `
|
|
207
|
-
- **kubectl**: `
|
|
208
|
-
- **Sprite**: `
|
|
253
|
+
### Trusted remotes
|
|
254
|
+
Configure `trustedRemotes` to auto-allow connections and recursively evaluate remote commands:
|
|
255
|
+
- **SSH**: `context: ssh` — also covers `scp` and `rsync`
|
|
256
|
+
- **Docker**: `context: docker` — for `docker exec`
|
|
257
|
+
- **kubectl**: `context: kubectl` — for `kubectl exec` (requires explicit `--context`)
|
|
258
|
+
- **Sprite**: `context: sprite` — for `sprite exec`/`console`
|
|
259
|
+
- **Fly.io**: `context: fly` — for `fly ssh console`
|
|
260
|
+
|
|
261
|
+
Remote names support glob patterns: `*`, `?`, `[...]`, `[!...]`, `{a,b,c}`
|
|
262
|
+
|
|
263
|
+
### Target-based policies
|
|
264
|
+
Configure `targetPolicies` to override decisions based on what a command touches:
|
|
265
|
+
- **Path**: allow or deny commands targeting specific files/directories, including `{{cwd}}`
|
|
266
|
+
- **Database**: match DB host, optional port, and optional database name
|
|
267
|
+
- **Endpoint**: match HTTP(S) endpoints for tools like `curl` and `wget`
|
|
209
268
|
|
|
210
|
-
|
|
269
|
+
Legacy aliases such as `trustedSSHHosts`, `trustedDockerContainers`, `trustedKubectlContexts`, `trustedSprites`, `trustedFlyApps`, `trustedPaths`, `trustedDatabases`, and `trustedEndpoints` are still supported, but new configs should prefer `trustedRemotes` and `targetPolicies`.
|
|
211
270
|
|
|
212
271
|
## How it works
|
|
213
272
|
|
|
214
273
|
1. Claude Code calls the `PreToolUse` hook before every Bash command
|
|
215
274
|
2. Warden parses the command into an AST via [bash-parser](https://github.com/vorpaljs/bash-parser), walking the tree to extract individual commands from pipes, chains, logical expressions, and subshells
|
|
216
275
|
3. Shell wrappers (`sh -c`, `bash -c`) and remote commands (`ssh`, `docker exec`, `kubectl exec`, `sprite exec`) are recursively parsed and evaluated
|
|
217
|
-
4. Each command is evaluated through the rule hierarchy: alwaysDeny → alwaysAllow → trusted remote
|
|
276
|
+
4. Each command is evaluated through the rule hierarchy: alwaysDeny → alwaysAllow → target-based policies → trusted remote contexts → command-specific rules with argument matching → default decision (checked per layer in priority order)
|
|
218
277
|
5. Results are combined: any deny → deny whole pipeline, any ask → ask, all allow → allow
|
|
219
278
|
6. Returns the decision via stdout JSON (allow/ask) or exit code 2 (deny), with a system message explaining the reasoning for deny/ask decisions
|
|
220
279
|
|
|
@@ -30,48 +30,100 @@ notifyOnDeny: true
|
|
|
30
30
|
# - nc
|
|
31
31
|
# - ncat
|
|
32
32
|
|
|
33
|
-
#
|
|
34
|
-
#
|
|
35
|
-
# Supports glob patterns (* wildcards).
|
|
36
|
-
#
|
|
37
|
-
#
|
|
38
|
-
#
|
|
39
|
-
# -
|
|
40
|
-
#
|
|
41
|
-
# -
|
|
33
|
+
# Remote execution contexts — SSH, Docker, kubectl, Sprite, Fly.io
|
|
34
|
+
# Commands on trusted remotes are recursively evaluated through warden rules.
|
|
35
|
+
# Supports glob patterns (* wildcards) for names.
|
|
36
|
+
# trustedRemotes:
|
|
37
|
+
# - context: ssh
|
|
38
|
+
# name: devserver
|
|
39
|
+
# - context: ssh
|
|
40
|
+
# name: staging-*
|
|
41
|
+
# - context: ssh
|
|
42
|
+
# name: "*.internal.company.com"
|
|
43
|
+
# - context: ssh
|
|
44
|
+
# name: prod-bastion
|
|
42
45
|
# overrides:
|
|
43
46
|
# alwaysAllow: [systemctl]
|
|
44
|
-
|
|
45
|
-
#
|
|
46
|
-
#
|
|
47
|
-
#
|
|
48
|
-
#
|
|
49
|
-
# -
|
|
50
|
-
#
|
|
51
|
-
# - name: staging-* # object with per-target overrides
|
|
47
|
+
# - context: docker
|
|
48
|
+
# name: my-app
|
|
49
|
+
# - context: docker
|
|
50
|
+
# name: dev-container
|
|
51
|
+
# allowAll: true # skip all checks (disposable env)
|
|
52
|
+
# - context: docker
|
|
53
|
+
# name: staging-*
|
|
52
54
|
# overrides:
|
|
53
55
|
# alwaysAllow: [sudo, apt]
|
|
54
|
-
|
|
55
|
-
#
|
|
56
|
-
#
|
|
57
|
-
#
|
|
58
|
-
# - minikube
|
|
59
|
-
# - name: dev-cluster-*
|
|
56
|
+
# - context: kubectl
|
|
57
|
+
# name: minikube
|
|
58
|
+
# - context: kubectl
|
|
59
|
+
# name: dev-cluster-*
|
|
60
60
|
# overrides:
|
|
61
61
|
# alwaysAllow: [sudo]
|
|
62
|
-
# -
|
|
62
|
+
# - context: kubectl
|
|
63
|
+
# name: prod-cluster
|
|
63
64
|
# overrides:
|
|
64
65
|
# alwaysDeny: [rm]
|
|
65
|
-
|
|
66
|
-
#
|
|
67
|
-
#
|
|
68
|
-
#
|
|
69
|
-
# - my-sprite # string → uses global overrides only
|
|
70
|
-
# - name: yudu-claw # allowAll: skip all checks (disposable env)
|
|
66
|
+
# - context: sprite
|
|
67
|
+
# name: my-sprite
|
|
68
|
+
# - context: sprite
|
|
69
|
+
# name: yudu-claw
|
|
71
70
|
# allowAll: true
|
|
72
|
-
# -
|
|
71
|
+
# - context: sprite
|
|
72
|
+
# name: dev-*
|
|
73
73
|
# overrides:
|
|
74
74
|
# alwaysAllow: [sudo, apt]
|
|
75
|
+
# - context: fly
|
|
76
|
+
# name: my-fly-app
|
|
77
|
+
# - context: fly
|
|
78
|
+
# name: staging-*
|
|
79
|
+
# allowAll: true
|
|
80
|
+
# - context: fly
|
|
81
|
+
# name: prod-app
|
|
82
|
+
# overrides:
|
|
83
|
+
# alwaysAllow: [sudo, apt]
|
|
84
|
+
|
|
85
|
+
# Target-based policies — override decisions based on paths, databases, or endpoints.
|
|
86
|
+
# targetPolicies:
|
|
87
|
+
# - type: path
|
|
88
|
+
# path: /tmp
|
|
89
|
+
# allowAll: true # any command targeting /tmp is auto-allowed
|
|
90
|
+
# - type: path
|
|
91
|
+
# path: "{{cwd}}" # expands to the project's working directory
|
|
92
|
+
# decision: allow
|
|
93
|
+
# commands: [rm, cp, mv] # only override these commands
|
|
94
|
+
# - type: path
|
|
95
|
+
# path: /etc
|
|
96
|
+
# decision: deny # block modifications to /etc
|
|
97
|
+
# reason: "System config directory"
|
|
98
|
+
# - type: path
|
|
99
|
+
# path: /opt/build
|
|
100
|
+
# recursive: false # exact match only (not children)
|
|
101
|
+
# decision: allow
|
|
102
|
+
# - type: database
|
|
103
|
+
# host: localhost
|
|
104
|
+
# decision: allow
|
|
105
|
+
# - type: database
|
|
106
|
+
# host: "dev-*.internal"
|
|
107
|
+
# database: "test_*"
|
|
108
|
+
# decision: allow
|
|
109
|
+
# - type: database
|
|
110
|
+
# host: "prod.example.com"
|
|
111
|
+
# decision: deny
|
|
112
|
+
# reason: "Production database"
|
|
113
|
+
# - type: endpoint
|
|
114
|
+
# pattern: "http://localhost:*"
|
|
115
|
+
# decision: allow
|
|
116
|
+
# - type: endpoint
|
|
117
|
+
# pattern: "https://api.dev.example.com/*"
|
|
118
|
+
# decision: allow
|
|
119
|
+
# - type: endpoint
|
|
120
|
+
# pattern: "https://api.prod.example.com/*"
|
|
121
|
+
# decision: deny
|
|
122
|
+
# reason: "Production API"
|
|
123
|
+
|
|
124
|
+
# Legacy keys (trustedSSHHosts, trustedDockerContainers, trustedKubectlContexts,
|
|
125
|
+
# trustedSprites, trustedFlyApps, trustedPaths, trustedDatabases, trustedEndpoints)
|
|
126
|
+
# are still supported and automatically converted to the unified form above.
|
|
75
127
|
|
|
76
128
|
# Override rules when evaluating commands inside trusted remote contexts
|
|
77
129
|
# (docker exec, kubectl exec, ssh, sprite exec). These overrides are applied
|