claude-warden 1.1.1 → 1.1.5
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/README.md +3 -3
- package/dist/index.cjs +44 -7
- package/package.json +10 -11
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ Warden hooks into Claude Code's `PreToolUse` event and **parses every shell comm
|
|
|
15
15
|
This AST-based approach enables:
|
|
16
16
|
|
|
17
17
|
- **Pipe and chain decomposition**: `cat file | grep pattern | wc -l` is parsed into three commands, each evaluated separately. All safe → auto-allow. One dangerous → deny the whole pipeline.
|
|
18
|
-
- **Argument-aware rules**: `git status` → allow, `git push --force` → prompt. `rm temp.txt` → allow, `rm -rf /` →
|
|
18
|
+
- **Argument-aware rules**: `git status` → allow, `git push --force` → prompt. `rm temp.txt` → allow, `rm -rf /` → prompt. The evaluator matches against argument patterns, not just command names.
|
|
19
19
|
- **Recursive evaluation of remote commands**: `ssh devserver 'cat /etc/hosts'` → Warden extracts the remote command, parses it through the same pipeline, and allows it. `ssh devserver 'sudo rm -rf /'` → denied. Same for `docker exec`, `kubectl exec`, and `sprite exec`.
|
|
20
20
|
- **Shell wrapper unwrapping**: `sh -c "npm run build && npm test"` → the inner command is extracted and recursively parsed/evaluated, not treated as an opaque string.
|
|
21
21
|
- **Env prefix handling**: `NODE_ENV=production npm run build` → correctly evaluates `npm run build`, ignoring the env prefix.
|
|
@@ -32,7 +32,7 @@ The result: **100+ common dev commands auto-approved**, dangerous commands auto-
|
|
|
32
32
|
| `cat file \| grep pattern \| wc -l` | Prompted | Auto-allowed (3 safe commands) |
|
|
33
33
|
| `npm run build && npm test` | Prompted | Auto-allowed |
|
|
34
34
|
| `git push --force origin main` | Prompted | Prompted (force push is risky) |
|
|
35
|
-
| `sudo rm -rf /` | Prompted | Auto-denied |
|
|
35
|
+
| `sudo rm -rf /` | Prompted | Auto-denied (sudo is blocked) |
|
|
36
36
|
| `ssh devserver cat /etc/hosts` | Prompted | Auto-allowed (trusted host + safe cmd) |
|
|
37
37
|
| `ssh devserver sudo rm -rf /` | Prompted | Auto-denied (trusted host + dangerous cmd) |
|
|
38
38
|
|
|
@@ -147,7 +147,7 @@ File readers (`cat`, `head`, `tail`, `less`), search tools (`grep`, `rg`, `find`
|
|
|
147
147
|
### Conditional rules
|
|
148
148
|
Commands like `node`, `npx`, `docker`, `ssh`, `git push --force`, `rm`, `chmod` have argument-aware rules. For example:
|
|
149
149
|
- `git` is allowed but `git push --force` triggers a prompt
|
|
150
|
-
- `rm temp.txt` is allowed but `rm -rf /` is
|
|
150
|
+
- `rm temp.txt` is allowed but `rm -rf /` is prompted
|
|
151
151
|
- `chmod 644 file` prompts but `chmod -R 777 /var` is denied
|
|
152
152
|
|
|
153
153
|
### Trusted remote targets
|
package/dist/index.cjs
CHANGED
|
@@ -18944,6 +18944,28 @@ var DEFAULT_CONFIG = {
|
|
|
18944
18944
|
{ match: { anyArgMatches: ["^--(version|help)$", "^-[vh]$"] }, decision: "allow", description: "Version/help flags" }
|
|
18945
18945
|
]
|
|
18946
18946
|
},
|
|
18947
|
+
// --- Shell interpreters ---
|
|
18948
|
+
{
|
|
18949
|
+
command: "bash",
|
|
18950
|
+
default: "ask",
|
|
18951
|
+
argPatterns: [
|
|
18952
|
+
{ match: { anyArgMatches: ["^--(version|help)$"] }, decision: "allow", description: "Version/help flags" }
|
|
18953
|
+
]
|
|
18954
|
+
},
|
|
18955
|
+
{
|
|
18956
|
+
command: "sh",
|
|
18957
|
+
default: "ask",
|
|
18958
|
+
argPatterns: [
|
|
18959
|
+
{ match: { anyArgMatches: ["^--(version|help)$"] }, decision: "allow", description: "Version/help flags" }
|
|
18960
|
+
]
|
|
18961
|
+
},
|
|
18962
|
+
{
|
|
18963
|
+
command: "zsh",
|
|
18964
|
+
default: "ask",
|
|
18965
|
+
argPatterns: [
|
|
18966
|
+
{ match: { anyArgMatches: ["^--(version|help)$"] }, decision: "allow", description: "Version/help flags" }
|
|
18967
|
+
]
|
|
18968
|
+
},
|
|
18947
18969
|
// --- Node.js ecosystem ---
|
|
18948
18970
|
{
|
|
18949
18971
|
command: "node",
|
|
@@ -18959,7 +18981,7 @@ var DEFAULT_CONFIG = {
|
|
|
18959
18981
|
default: "ask",
|
|
18960
18982
|
argPatterns: [
|
|
18961
18983
|
{
|
|
18962
|
-
match: { anyArgMatches: ["^(jest|vitest|tsx|ts-node|tsc|eslint|prettier|mkdirp|concurrently|turbo|next|nuxt|vite|astro|playwright|cypress|mocha|nyc|c8|nodemon|ts-jest|tsup|esbuild|rollup|webpack|prisma|drizzle-kit|typeorm|knex|sequelize-cli|tailwindcss|postcss|autoprefixer|lint-staged|husky|changeset|semantic-release|lerna|nx|create-react-app|create-next-app|create-vite|degit|storybook|wrangler|netlify|vercel)$"] },
|
|
18984
|
+
match: { anyArgMatches: ["^(jest|vitest|tsx|ts-node|tsc|eslint|prettier|mkdirp|concurrently|turbo|next|nuxt|vite|astro|playwright|cypress|mocha|nyc|c8|nodemon|ts-jest|tsup|esbuild|rollup|webpack|prisma|drizzle-kit|typeorm|knex|sequelize-cli|tailwindcss|postcss|autoprefixer|lint-staged|husky|changeset|semantic-release|lerna|nx|create-react-app|create-next-app|create-vite|degit|storybook|wrangler|netlify|vercel|json)$"] },
|
|
18963
18985
|
decision: "allow",
|
|
18964
18986
|
description: "Well-known dev tools"
|
|
18965
18987
|
},
|
|
@@ -18971,7 +18993,7 @@ var DEFAULT_CONFIG = {
|
|
|
18971
18993
|
default: "ask",
|
|
18972
18994
|
argPatterns: [
|
|
18973
18995
|
{
|
|
18974
|
-
match: { anyArgMatches: ["^(jest|vitest|tsx|ts-node|tsc|eslint|prettier|mkdirp|concurrently|turbo|next|nuxt|vite|astro|playwright|cypress|mocha|nyc|c8|nodemon|ts-jest|tsup|esbuild|rollup|webpack|prisma|drizzle-kit|typeorm|knex|sequelize-cli|tailwindcss|postcss|autoprefixer|lint-staged|husky|changeset|semantic-release|lerna|nx|create-react-app|create-next-app|create-vite|degit|storybook|wrangler|netlify|vercel)$"] },
|
|
18996
|
+
match: { anyArgMatches: ["^(jest|vitest|tsx|ts-node|tsc|eslint|prettier|mkdirp|concurrently|turbo|next|nuxt|vite|astro|playwright|cypress|mocha|nyc|c8|nodemon|ts-jest|tsup|esbuild|rollup|webpack|prisma|drizzle-kit|typeorm|knex|sequelize-cli|tailwindcss|postcss|autoprefixer|lint-staged|husky|changeset|semantic-release|lerna|nx|create-react-app|create-next-app|create-vite|degit|storybook|wrangler|netlify|vercel|json)$"] },
|
|
18975
18997
|
decision: "allow",
|
|
18976
18998
|
description: "Well-known dev tools"
|
|
18977
18999
|
},
|
|
@@ -19088,7 +19110,7 @@ var DEFAULT_CONFIG = {
|
|
|
19088
19110
|
command: "rm",
|
|
19089
19111
|
default: "ask",
|
|
19090
19112
|
argPatterns: [
|
|
19091
|
-
{ match: { argsMatch: ["-[^\\s]*r[^\\s]*f|-[^\\s]*f[^\\s]*r"] }, decision: "
|
|
19113
|
+
{ match: { argsMatch: ["-[^\\s]*r[^\\s]*f|-[^\\s]*f[^\\s]*r"] }, decision: "ask", reason: "Recursive force delete (rm -rf)" },
|
|
19092
19114
|
{ match: { argsMatch: ["-[^\\s]*r"] }, decision: "ask", reason: "Recursive delete" },
|
|
19093
19115
|
{ match: { argCount: { max: 3 }, not: false }, decision: "allow", description: "Deleting a small number of non-recursive files" }
|
|
19094
19116
|
]
|
|
@@ -19243,9 +19265,12 @@ function generateAllowSnippet(details) {
|
|
|
19243
19265
|
return lines.join("\n");
|
|
19244
19266
|
}
|
|
19245
19267
|
function formatSystemMessage(decision, rawCommand, details) {
|
|
19246
|
-
const header = decision === "deny" ? "[warden] Command blocked" : "[warden] Command flagged for review";
|
|
19247
|
-
const lines = [header, ""];
|
|
19248
19268
|
const relevant = details.filter((d) => d.decision !== "allow");
|
|
19269
|
+
if (decision === "ask") {
|
|
19270
|
+
const parts = relevant.map((d) => `\`${d.command}\`: ${d.reason}`);
|
|
19271
|
+
return `[warden] ${parts.join(" | ")} \u2014 To auto-allow, see /warden-allow`;
|
|
19272
|
+
}
|
|
19273
|
+
const lines = ["[warden] Command blocked", ""];
|
|
19249
19274
|
if (relevant.length > 0) {
|
|
19250
19275
|
for (const d of relevant) {
|
|
19251
19276
|
lines.push(`- \`${d.command}\`: ${d.reason}`);
|
|
@@ -19304,14 +19329,26 @@ async function main() {
|
|
|
19304
19329
|
}
|
|
19305
19330
|
if (result.decision === "deny") {
|
|
19306
19331
|
const msg2 = formatSystemMessage("deny", command, result.details);
|
|
19307
|
-
const output2 = {
|
|
19332
|
+
const output2 = {
|
|
19333
|
+
hookSpecificOutput: {
|
|
19334
|
+
hookEventName: "PreToolUse",
|
|
19335
|
+
permissionDecision: "deny",
|
|
19336
|
+
permissionDecisionReason: msg2
|
|
19337
|
+
}
|
|
19338
|
+
};
|
|
19308
19339
|
process.stdout.write(JSON.stringify(output2));
|
|
19309
19340
|
process.stderr.write(`[warden] Blocked: ${result.reason}
|
|
19310
19341
|
`);
|
|
19311
19342
|
process.exit(2);
|
|
19312
19343
|
}
|
|
19313
19344
|
const msg = formatSystemMessage("ask", command, result.details);
|
|
19314
|
-
const output = {
|
|
19345
|
+
const output = {
|
|
19346
|
+
hookSpecificOutput: {
|
|
19347
|
+
hookEventName: "PreToolUse",
|
|
19348
|
+
permissionDecision: "ask",
|
|
19349
|
+
permissionDecisionReason: msg
|
|
19350
|
+
}
|
|
19351
|
+
};
|
|
19315
19352
|
process.stdout.write(JSON.stringify(output));
|
|
19316
19353
|
process.exit(0);
|
|
19317
19354
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-warden",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.5",
|
|
4
4
|
"description": "Smart command safety filter for Claude Code — auto-approves safe commands, blocks dangerous ones",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
@@ -28,15 +28,6 @@
|
|
|
28
28
|
"README.md",
|
|
29
29
|
"LICENSE"
|
|
30
30
|
],
|
|
31
|
-
"scripts": {
|
|
32
|
-
"build": "tsup",
|
|
33
|
-
"dev": "tsup --watch",
|
|
34
|
-
"test": "vitest run",
|
|
35
|
-
"test:watch": "vitest",
|
|
36
|
-
"typecheck": "tsc --noEmit",
|
|
37
|
-
"eval": "node dist/index.cjs",
|
|
38
|
-
"prepublishOnly": "pnpm run build && pnpm run test"
|
|
39
|
-
},
|
|
40
31
|
"devDependencies": {
|
|
41
32
|
"@types/node": "^20.0.0",
|
|
42
33
|
"bash-parser": "^0.5.0",
|
|
@@ -44,5 +35,13 @@
|
|
|
44
35
|
"typescript": "^5.4.0",
|
|
45
36
|
"vitest": "^1.6.0",
|
|
46
37
|
"yaml": "^2.4.0"
|
|
38
|
+
},
|
|
39
|
+
"scripts": {
|
|
40
|
+
"build": "tsup",
|
|
41
|
+
"dev": "tsup --watch",
|
|
42
|
+
"test": "vitest run",
|
|
43
|
+
"test:watch": "vitest",
|
|
44
|
+
"typecheck": "tsc --noEmit",
|
|
45
|
+
"eval": "node dist/index.cjs"
|
|
47
46
|
}
|
|
48
|
-
}
|
|
47
|
+
}
|