claude-warden 1.3.1 → 1.5.1
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/config/warden.default.yaml +6 -0
- package/dist/index.cjs +254 -4
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-warden",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.1",
|
|
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"
|
|
@@ -13,6 +13,12 @@ defaultDecision: ask
|
|
|
13
13
|
# If true, commands containing $() or backticks trigger "ask"
|
|
14
14
|
askOnSubshell: true
|
|
15
15
|
|
|
16
|
+
# Send OS notifications when warden prompts for permission or blocks a command.
|
|
17
|
+
# On macOS, uses terminal-notifier (click to activate terminal) or osascript fallback.
|
|
18
|
+
# On Linux, uses notify-send.
|
|
19
|
+
notifyOnAsk: true
|
|
20
|
+
notifyOnDeny: true
|
|
21
|
+
|
|
16
22
|
# Additional commands to always allow (checked after alwaysDeny within this scope)
|
|
17
23
|
# alwaysAllow:
|
|
18
24
|
# - terraform
|
package/dist/index.cjs
CHANGED
|
@@ -18988,6 +18988,8 @@ function pkgRunnerRule(command) {
|
|
|
18988
18988
|
var DEFAULT_CONFIG = {
|
|
18989
18989
|
defaultDecision: "ask",
|
|
18990
18990
|
askOnSubshell: true,
|
|
18991
|
+
notifyOnAsk: true,
|
|
18992
|
+
notifyOnDeny: true,
|
|
18991
18993
|
trustedSSHHosts: [],
|
|
18992
18994
|
trustedDockerContainers: [],
|
|
18993
18995
|
trustedKubectlContexts: [],
|
|
@@ -19092,6 +19094,7 @@ var DEFAULT_CONFIG = {
|
|
|
19092
19094
|
"ifconfig",
|
|
19093
19095
|
"ip",
|
|
19094
19096
|
"nmap",
|
|
19097
|
+
"arp",
|
|
19095
19098
|
// Pagers and formatters
|
|
19096
19099
|
"bat",
|
|
19097
19100
|
"pygmentize",
|
|
@@ -19106,6 +19109,74 @@ var DEFAULT_CONFIG = {
|
|
|
19106
19109
|
"tput",
|
|
19107
19110
|
"reset",
|
|
19108
19111
|
"clear",
|
|
19112
|
+
// System/hardware info
|
|
19113
|
+
"lscpu",
|
|
19114
|
+
"lsblk",
|
|
19115
|
+
"lsusb",
|
|
19116
|
+
"lspci",
|
|
19117
|
+
"lsmod",
|
|
19118
|
+
"dmesg",
|
|
19119
|
+
"sysctl",
|
|
19120
|
+
"sw_vers",
|
|
19121
|
+
"system_profiler",
|
|
19122
|
+
"hostinfo",
|
|
19123
|
+
"lsb_release",
|
|
19124
|
+
"hostnamectl",
|
|
19125
|
+
"arch",
|
|
19126
|
+
"getconf",
|
|
19127
|
+
// User/group info
|
|
19128
|
+
"groups",
|
|
19129
|
+
"getent",
|
|
19130
|
+
"w",
|
|
19131
|
+
"last",
|
|
19132
|
+
"lastlog",
|
|
19133
|
+
"finger",
|
|
19134
|
+
"users",
|
|
19135
|
+
// Process info
|
|
19136
|
+
"pgrep",
|
|
19137
|
+
"pidof",
|
|
19138
|
+
"jobs",
|
|
19139
|
+
// Compression/archive
|
|
19140
|
+
"tar",
|
|
19141
|
+
"gzip",
|
|
19142
|
+
"gunzip",
|
|
19143
|
+
"bzip2",
|
|
19144
|
+
"bunzip2",
|
|
19145
|
+
"xz",
|
|
19146
|
+
"unxz",
|
|
19147
|
+
"zip",
|
|
19148
|
+
"unzip",
|
|
19149
|
+
"7z",
|
|
19150
|
+
"zcat",
|
|
19151
|
+
"bzcat",
|
|
19152
|
+
"xzcat",
|
|
19153
|
+
"zless",
|
|
19154
|
+
"zmore",
|
|
19155
|
+
"zgrep",
|
|
19156
|
+
// Clipboard
|
|
19157
|
+
"pbcopy",
|
|
19158
|
+
"pbpaste",
|
|
19159
|
+
"xclip",
|
|
19160
|
+
"xsel",
|
|
19161
|
+
"wl-copy",
|
|
19162
|
+
"wl-paste",
|
|
19163
|
+
// Binary analysis
|
|
19164
|
+
"strings",
|
|
19165
|
+
"nm",
|
|
19166
|
+
"objdump",
|
|
19167
|
+
"readelf",
|
|
19168
|
+
"ldd",
|
|
19169
|
+
"otool",
|
|
19170
|
+
"size",
|
|
19171
|
+
// macOS utilities (read-only)
|
|
19172
|
+
"mdfind",
|
|
19173
|
+
"mdls",
|
|
19174
|
+
"mdutil",
|
|
19175
|
+
"plutil",
|
|
19176
|
+
"sips",
|
|
19177
|
+
"xcode-select",
|
|
19178
|
+
"xcrun",
|
|
19179
|
+
"xcodebuild",
|
|
19109
19180
|
// Misc safe
|
|
19110
19181
|
"cd",
|
|
19111
19182
|
"pushd",
|
|
@@ -19123,7 +19194,18 @@ var DEFAULT_CONFIG = {
|
|
|
19123
19194
|
"shasum",
|
|
19124
19195
|
"cksum",
|
|
19125
19196
|
"base64",
|
|
19126
|
-
"openssl"
|
|
19197
|
+
"openssl",
|
|
19198
|
+
"watch",
|
|
19199
|
+
"timeout",
|
|
19200
|
+
"nohup",
|
|
19201
|
+
"nice",
|
|
19202
|
+
"iconv",
|
|
19203
|
+
"locale",
|
|
19204
|
+
"localedef",
|
|
19205
|
+
"numfmt",
|
|
19206
|
+
"factor",
|
|
19207
|
+
"bc",
|
|
19208
|
+
"dc"
|
|
19127
19209
|
],
|
|
19128
19210
|
alwaysDeny: [
|
|
19129
19211
|
"sudo",
|
|
@@ -19147,7 +19229,9 @@ var DEFAULT_CONFIG = {
|
|
|
19147
19229
|
"crontab",
|
|
19148
19230
|
"systemctl",
|
|
19149
19231
|
"service",
|
|
19150
|
-
"launchctl"
|
|
19232
|
+
"launchctl",
|
|
19233
|
+
"wipefs",
|
|
19234
|
+
"shred"
|
|
19151
19235
|
],
|
|
19152
19236
|
rules: [
|
|
19153
19237
|
// --- CLI tools ---
|
|
@@ -19262,7 +19346,15 @@ var DEFAULT_CONFIG = {
|
|
|
19262
19346
|
]
|
|
19263
19347
|
},
|
|
19264
19348
|
{ command: "docker-compose", default: "ask" },
|
|
19265
|
-
{
|
|
19349
|
+
{
|
|
19350
|
+
command: "kubectl",
|
|
19351
|
+
default: "ask",
|
|
19352
|
+
argPatterns: [
|
|
19353
|
+
{ match: { anyArgMatches: ["^(get|describe|logs|top|explain|api-resources|api-versions|version|config|cluster-info)$"] }, decision: "allow", description: "Read-only kubectl commands" },
|
|
19354
|
+
{ match: { anyArgMatches: ["^(delete|drain|cordon|taint)$"] }, decision: "ask", reason: "Destructive kubectl operation" },
|
|
19355
|
+
VERSION_HELP_FLAGS
|
|
19356
|
+
]
|
|
19357
|
+
},
|
|
19266
19358
|
// --- File operations ---
|
|
19267
19359
|
{
|
|
19268
19360
|
command: "rm",
|
|
@@ -19302,7 +19394,92 @@ var DEFAULT_CONFIG = {
|
|
|
19302
19394
|
// --- Terraform / IaC ---
|
|
19303
19395
|
{ command: "terraform", default: "ask", argPatterns: [
|
|
19304
19396
|
{ match: { anyArgMatches: ["^(plan|validate|fmt|show|state|output|providers|version|graph|console)$"] }, decision: "allow", description: "Read-only terraform commands" }
|
|
19305
|
-
] }
|
|
19397
|
+
] },
|
|
19398
|
+
// --- macOS open ---
|
|
19399
|
+
{ command: "open", default: "ask" },
|
|
19400
|
+
// --- Text editors ---
|
|
19401
|
+
...["vi", "vim", "nvim", "nano", "emacs"].map((cmd) => ({
|
|
19402
|
+
command: cmd,
|
|
19403
|
+
default: "ask",
|
|
19404
|
+
argPatterns: [VERSION_HELP_FLAGS]
|
|
19405
|
+
})),
|
|
19406
|
+
// --- Scripting languages ---
|
|
19407
|
+
...["ruby", "perl", "php"].map((cmd) => ({
|
|
19408
|
+
command: cmd,
|
|
19409
|
+
default: "ask",
|
|
19410
|
+
argPatterns: [
|
|
19411
|
+
{ match: { anyArgMatches: ["^-e$", "^--eval"] }, decision: "ask", reason: "Inline code execution" },
|
|
19412
|
+
VERSION_HELP_FLAGS
|
|
19413
|
+
]
|
|
19414
|
+
})),
|
|
19415
|
+
// --- Java ecosystem ---
|
|
19416
|
+
{ command: "java", default: "ask", argPatterns: [VERSION_HELP_FLAGS] },
|
|
19417
|
+
{ command: "javac", default: "allow" },
|
|
19418
|
+
// --- Swift / Zig / Dotnet ---
|
|
19419
|
+
{ command: "swift", default: "allow", argPatterns: [
|
|
19420
|
+
{ match: { anyArgMatches: ["^(build|test|run|package)$"] }, decision: "allow" }
|
|
19421
|
+
] },
|
|
19422
|
+
{ command: "swiftc", default: "allow" },
|
|
19423
|
+
{ command: "zig", default: "allow" },
|
|
19424
|
+
{ command: "dotnet", default: "allow", argPatterns: [
|
|
19425
|
+
{ match: { anyArgMatches: ["^(publish|nuget)$"] }, decision: "ask", reason: "Publishing" }
|
|
19426
|
+
] },
|
|
19427
|
+
// --- Database CLIs ---
|
|
19428
|
+
...["psql", "mysql", "mariadb", "sqlite3", "redis-cli", "mongosh"].map((cmd) => ({
|
|
19429
|
+
command: cmd,
|
|
19430
|
+
default: "ask",
|
|
19431
|
+
argPatterns: [VERSION_HELP_FLAGS]
|
|
19432
|
+
})),
|
|
19433
|
+
// --- Cloud CLIs ---
|
|
19434
|
+
{ command: "gcloud", default: "ask", argPatterns: [
|
|
19435
|
+
{ match: { anyArgMatches: ["^(info|version|help|config|components)$"] }, decision: "allow", description: "Config/info" },
|
|
19436
|
+
{ match: { anyArgMatches: ["^(list|describe|get-iam-policy|get)$"] }, decision: "allow", description: "Read-only ops" },
|
|
19437
|
+
VERSION_HELP_FLAGS
|
|
19438
|
+
] },
|
|
19439
|
+
{ command: "az", default: "ask", argPatterns: [
|
|
19440
|
+
{ match: { anyArgMatches: ["^(list|show|get)$"] }, decision: "allow", description: "Read-only ops" },
|
|
19441
|
+
VERSION_HELP_FLAGS
|
|
19442
|
+
] },
|
|
19443
|
+
{ command: "aws", default: "ask", argPatterns: [
|
|
19444
|
+
{ match: { anyArgMatches: ["^(describe|list|get|sts)$"] }, decision: "allow", description: "Read-only ops" },
|
|
19445
|
+
VERSION_HELP_FLAGS
|
|
19446
|
+
] },
|
|
19447
|
+
// --- Helm ---
|
|
19448
|
+
{ command: "helm", default: "ask", argPatterns: [
|
|
19449
|
+
{ match: { anyArgMatches: ["^(list|search|show|status|get|template|version|env|history)$"] }, decision: "allow", description: "Read-only helm commands" },
|
|
19450
|
+
VERSION_HELP_FLAGS
|
|
19451
|
+
] },
|
|
19452
|
+
// --- Screen/tmux ---
|
|
19453
|
+
...["screen", "tmux"].map((cmd) => ({
|
|
19454
|
+
command: cmd,
|
|
19455
|
+
default: "ask",
|
|
19456
|
+
argPatterns: [
|
|
19457
|
+
{ match: { anyArgMatches: ["^(list-sessions|ls|list)$"] }, decision: "allow", description: "List sessions" },
|
|
19458
|
+
VERSION_HELP_FLAGS
|
|
19459
|
+
]
|
|
19460
|
+
})),
|
|
19461
|
+
// --- GPG ---
|
|
19462
|
+
{ command: "gpg", default: "ask", argPatterns: [
|
|
19463
|
+
{ match: { anyArgMatches: ["^(--verify|--list-keys|--list-secret-keys|--fingerprint)$"] }, decision: "allow", description: "Read-only gpg" },
|
|
19464
|
+
VERSION_HELP_FLAGS
|
|
19465
|
+
] },
|
|
19466
|
+
// --- macOS-specific ---
|
|
19467
|
+
{ command: "defaults", default: "ask", argPatterns: [
|
|
19468
|
+
{ match: { anyArgMatches: ["^(read|read-type|find|domains)$"] }, decision: "allow", description: "Read-only defaults operations" }
|
|
19469
|
+
] },
|
|
19470
|
+
{ command: "diskutil", default: "ask", argPatterns: [
|
|
19471
|
+
{ match: { anyArgMatches: ["^(list|info|apfs|cs|appleRAID)$"] }, decision: "allow", description: "Read-only diskutil" }
|
|
19472
|
+
] },
|
|
19473
|
+
{ command: "codesign", default: "ask", argPatterns: [
|
|
19474
|
+
{ match: { anyArgMatches: ["^(-vv|--verify|--display|-d)$"] }, decision: "allow", description: "Verify codesign" }
|
|
19475
|
+
] },
|
|
19476
|
+
{ command: "osascript", default: "ask" },
|
|
19477
|
+
{ command: "say", default: "ask" },
|
|
19478
|
+
// --- Process management ---
|
|
19479
|
+
{ command: "kill", default: "ask" },
|
|
19480
|
+
{ command: "killall", default: "ask" },
|
|
19481
|
+
{ command: "pkill", default: "ask" },
|
|
19482
|
+
{ command: "renice", default: "ask" }
|
|
19306
19483
|
]
|
|
19307
19484
|
}]
|
|
19308
19485
|
};
|
|
@@ -19403,6 +19580,12 @@ function mergeNonLayerFields(config, raw) {
|
|
|
19403
19580
|
if (typeof raw.askOnSubshell === "boolean") {
|
|
19404
19581
|
config.askOnSubshell = raw.askOnSubshell;
|
|
19405
19582
|
}
|
|
19583
|
+
if (typeof raw.notifyOnAsk === "boolean") {
|
|
19584
|
+
config.notifyOnAsk = raw.notifyOnAsk;
|
|
19585
|
+
}
|
|
19586
|
+
if (typeof raw.notifyOnDeny === "boolean") {
|
|
19587
|
+
config.notifyOnDeny = raw.notifyOnDeny;
|
|
19588
|
+
}
|
|
19406
19589
|
if (raw.trustedContextOverrides && typeof raw.trustedContextOverrides === "object") {
|
|
19407
19590
|
const overrides = raw.trustedContextOverrides;
|
|
19408
19591
|
const layer = extractLayer(overrides);
|
|
@@ -19491,6 +19674,62 @@ See /claude-warden:warden-allow`;
|
|
|
19491
19674
|
return lines.join("\n");
|
|
19492
19675
|
}
|
|
19493
19676
|
|
|
19677
|
+
// src/notify.ts
|
|
19678
|
+
var import_child_process = require("child_process");
|
|
19679
|
+
var TERMINAL_BUNDLE_IDS = {
|
|
19680
|
+
"iTerm.app": "com.googlecode.iterm2",
|
|
19681
|
+
"Apple_Terminal": "com.apple.Terminal",
|
|
19682
|
+
"Alacritty": "com.github.alacritty.Alacritty",
|
|
19683
|
+
"WezTerm": "io.wezfurlong.wezterm"
|
|
19684
|
+
};
|
|
19685
|
+
var terminalNotifierAvailable = null;
|
|
19686
|
+
function hasTerminalNotifier() {
|
|
19687
|
+
if (terminalNotifierAvailable !== null) return terminalNotifierAvailable;
|
|
19688
|
+
try {
|
|
19689
|
+
(0, import_child_process.execFileSync)("which", ["terminal-notifier"], { stdio: "ignore" });
|
|
19690
|
+
terminalNotifierAvailable = true;
|
|
19691
|
+
} catch {
|
|
19692
|
+
terminalNotifierAvailable = false;
|
|
19693
|
+
}
|
|
19694
|
+
return terminalNotifierAvailable;
|
|
19695
|
+
}
|
|
19696
|
+
function getBundleId() {
|
|
19697
|
+
const termProgram = process.env.TERM_PROGRAM;
|
|
19698
|
+
if (!termProgram) return void 0;
|
|
19699
|
+
return TERMINAL_BUNDLE_IDS[termProgram];
|
|
19700
|
+
}
|
|
19701
|
+
function buildNotifyCommand(title, message) {
|
|
19702
|
+
const platform = process.platform;
|
|
19703
|
+
if (platform === "darwin") {
|
|
19704
|
+
if (hasTerminalNotifier()) {
|
|
19705
|
+
const args2 = ["-title", title, "-message", message];
|
|
19706
|
+
const bundleId = getBundleId();
|
|
19707
|
+
if (bundleId) {
|
|
19708
|
+
args2.push("-activate", bundleId);
|
|
19709
|
+
}
|
|
19710
|
+
return { cmd: "terminal-notifier", args: args2 };
|
|
19711
|
+
}
|
|
19712
|
+
const script = `display notification ${JSON.stringify(message)} with title ${JSON.stringify(title)}`;
|
|
19713
|
+
return { cmd: "osascript", args: ["-e", script] };
|
|
19714
|
+
}
|
|
19715
|
+
if (platform === "linux") {
|
|
19716
|
+
return { cmd: "notify-send", args: [title, message] };
|
|
19717
|
+
}
|
|
19718
|
+
return null;
|
|
19719
|
+
}
|
|
19720
|
+
function sendNotification(title, message, config) {
|
|
19721
|
+
try {
|
|
19722
|
+
const notifyCmd = buildNotifyCommand(title, message);
|
|
19723
|
+
if (!notifyCmd) return;
|
|
19724
|
+
const child = (0, import_child_process.spawn)(notifyCmd.cmd, notifyCmd.args, {
|
|
19725
|
+
detached: true,
|
|
19726
|
+
stdio: "ignore"
|
|
19727
|
+
});
|
|
19728
|
+
child.unref();
|
|
19729
|
+
} catch {
|
|
19730
|
+
}
|
|
19731
|
+
}
|
|
19732
|
+
|
|
19494
19733
|
// src/index.ts
|
|
19495
19734
|
async function main() {
|
|
19496
19735
|
let raw = "";
|
|
@@ -19506,6 +19745,9 @@ async function main() {
|
|
|
19506
19745
|
if (input.tool_name !== "Bash") {
|
|
19507
19746
|
process.exit(0);
|
|
19508
19747
|
}
|
|
19748
|
+
if (input.permission_mode === "dangerously-skip-permissions") {
|
|
19749
|
+
process.exit(0);
|
|
19750
|
+
}
|
|
19509
19751
|
const command = input.tool_input?.command;
|
|
19510
19752
|
if (!command || typeof command !== "string") {
|
|
19511
19753
|
process.exit(0);
|
|
@@ -19525,6 +19767,10 @@ async function main() {
|
|
|
19525
19767
|
process.exit(0);
|
|
19526
19768
|
}
|
|
19527
19769
|
if (result.decision === "deny") {
|
|
19770
|
+
if (config.notifyOnDeny) {
|
|
19771
|
+
const truncated = command.length > 80 ? command.slice(0, 77) + "..." : command;
|
|
19772
|
+
sendNotification("Claude Warden", `Blocked: ${truncated}`, config);
|
|
19773
|
+
}
|
|
19528
19774
|
const msg2 = formatSystemMessage("deny", command, result.details);
|
|
19529
19775
|
const output2 = {
|
|
19530
19776
|
hookSpecificOutput: {
|
|
@@ -19538,6 +19784,10 @@ async function main() {
|
|
|
19538
19784
|
`);
|
|
19539
19785
|
process.exit(2);
|
|
19540
19786
|
}
|
|
19787
|
+
if (config.notifyOnAsk) {
|
|
19788
|
+
const truncated = command.length > 80 ? command.slice(0, 77) + "..." : command;
|
|
19789
|
+
sendNotification("Claude Warden", `Permission needed: ${truncated}`, config);
|
|
19790
|
+
}
|
|
19541
19791
|
const msg = formatSystemMessage("ask", command, result.details);
|
|
19542
19792
|
const output = {
|
|
19543
19793
|
hookSpecificOutput: {
|