cc-safe-setup 29.7.0 → 30.0.4

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.
Files changed (1022) hide show
  1. package/.claude-plugin/marketplace.json +72 -19
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CONTRIBUTING.md +7 -2
  4. package/COOKBOOK.md +50 -46
  5. package/LICENSE +21 -0
  6. package/MIGRATION.md +8 -8
  7. package/README.md +419 -512
  8. package/SAFETY_CHECKLIST.md +15 -7
  9. package/SERVICES.md +194 -0
  10. package/SETTINGS_REFERENCE.md +236 -17
  11. package/SKILL.md +5 -5
  12. package/TROUBLESHOOTING.md +35 -14
  13. package/action.yml +12 -4
  14. package/audit/README.md +84 -0
  15. package/audit/audit-checklist.md +152 -0
  16. package/audit/boundary-selftest.sh +85 -0
  17. package/audit/boundary.sh +123 -0
  18. package/audit/count-hooks.py +42 -0
  19. package/audit/find-dead-hooks.sh +82 -0
  20. package/audit/find-unfirable-rules.sh +142 -0
  21. package/audit/fire.sh +97 -0
  22. package/audit/selftest.sh +42 -0
  23. package/audit/unfirable-selftest.sh +81 -0
  24. package/audit-web/index.html +9 -9
  25. package/examples/README.md +54 -17
  26. package/examples/account-billing-log.sh +98 -0
  27. package/examples/account-routing-preflight.sh +123 -0
  28. package/examples/agent-sdk-credit-pool-monitor.sh +145 -0
  29. package/examples/agent-view-quota-decrement.sh +32 -0
  30. package/examples/agent-view-quota-warn.sh +94 -0
  31. package/examples/agents-md-edit-drift-warner.sh +223 -0
  32. package/examples/agents-md-loader.sh +160 -0
  33. package/examples/agents-md-sync-checker.sh +102 -0
  34. package/examples/ai-slop-punctuation-arrest.sh +210 -0
  35. package/examples/allowlist.sh +70 -10
  36. package/examples/always-allow-pattern-suggester.sh +125 -0
  37. package/examples/ansible-vault-guard.sh +2 -1
  38. package/examples/anthropic-base-url-guard.sh +76 -0
  39. package/examples/api-busyloop-guard.sh +123 -0
  40. package/examples/api-endpoint-guard.sh +12 -0
  41. package/examples/api-key-in-url-guard.sh +17 -1
  42. package/examples/api-rate-limit-guard.sh +36 -1
  43. package/examples/api-rate-limit-tracker.sh +12 -0
  44. package/examples/articulated-scope-capture.sh +101 -0
  45. package/examples/askuserquestion-autonomy-gate.sh +102 -0
  46. package/examples/attachment-traversal-guard.sh +118 -0
  47. package/examples/aup-block-pattern-logger.sh +161 -0
  48. package/examples/aup-false-positive-helper.sh +124 -0
  49. package/examples/aup-large-tool-output-warner.sh +282 -0
  50. package/examples/aup-retry-loop-guard.sh +229 -0
  51. package/examples/auth-expiry-reminder.sh +157 -0
  52. package/examples/auth-macos-sleep-detector.sh +185 -0
  53. package/examples/auth-path-detector.sh +171 -0
  54. package/examples/auth-status-checker.sh +157 -0
  55. package/examples/authorized-reconfirmation-detector.sh +195 -0
  56. package/examples/auto-approve-build.sh +39 -0
  57. package/examples/auto-approve-cargo.sh +31 -1
  58. package/examples/auto-approve-docker.sh +35 -0
  59. package/examples/auto-approve-git-read.sh +37 -14
  60. package/examples/auto-approve-go.sh +30 -1
  61. package/examples/auto-approve-gradle.sh +29 -1
  62. package/examples/auto-approve-make.sh +29 -1
  63. package/examples/auto-approve-maven.sh +29 -1
  64. package/examples/auto-approve-python.sh +41 -1
  65. package/examples/auto-approve-readonly-tools.sh +1 -0
  66. package/examples/auto-approve-readonly.sh +110 -33
  67. package/examples/auto-approve-ssh.sh +30 -1
  68. package/examples/auto-approve-test.sh +44 -0
  69. package/examples/auto-checkpoint.sh +1 -1
  70. package/examples/auto-compact-prep.sh +0 -0
  71. package/examples/auto-git-checkpoint.sh +0 -0
  72. package/examples/auto-mode-safe-commands.sh +53 -1
  73. package/examples/auto-mode-safety-enforcer.sh +151 -4
  74. package/examples/auto-push-session-branch.sh +22 -0
  75. package/examples/aws-production-guard.sh +13 -1
  76. package/examples/aws-region-guard.sh +1 -1
  77. package/examples/background-cost-launch-guard.sh +82 -0
  78. package/examples/background-task-guard.sh +12 -0
  79. package/examples/backup-before-refactor.sh +0 -0
  80. package/examples/banned-command-guard.sh +12 -0
  81. package/examples/bash-allowlist-secondary-check.sh +157 -0
  82. package/examples/bash-domain-allowlist.sh +12 -0
  83. package/examples/bash-fanout-bounded-rewriter.sh +191 -0
  84. package/examples/bash-heuristic-approver.sh +112 -10
  85. package/examples/bash-project-fence.sh +194 -0
  86. package/examples/bash-safety-auto-deny.sh +12 -0
  87. package/examples/bash-secret-output-detector.sh +44 -3
  88. package/examples/bash-trace-guard.sh +12 -0
  89. package/examples/bashrc-safety-check.sh +0 -0
  90. package/examples/bg-permission-prompt-warner.sh +182 -0
  91. package/examples/bg-task-cooldown-guard.sh +12 -0
  92. package/examples/binary-read-detector.sh +135 -0
  93. package/examples/binary-upload-guard.sh +12 -0
  94. package/examples/block-database-wipe.sh +35 -10
  95. package/examples/branch-name-check.sh +8 -3
  96. package/examples/branch-naming-convention.sh +0 -0
  97. package/examples/broad-find-guard.sh +12 -0
  98. package/examples/broad-prefix-session-trap-warner.sh +106 -0
  99. package/examples/bulk-file-delete-guard.sh +45 -0
  100. package/examples/bypass-mode-effective-verifier.sh +203 -0
  101. package/examples/cache-creation-drift-detector.sh +120 -0
  102. package/examples/cache-residue-detector.sh +195 -0
  103. package/examples/cache-tier-logger.sh +70 -0
  104. package/examples/cache-ttl-eviction-detector.sh +149 -0
  105. package/examples/cargo-publish-guard.sh +14 -1
  106. package/examples/case-insensitive-path-guard.sh +21 -2
  107. package/examples/case-sensitive-guard.sh +23 -2
  108. package/examples/cch-cache-guard.sh +0 -0
  109. package/examples/cch-sentinel-precommit-guard.sh +47 -0
  110. package/examples/check-abort-controller.sh +1 -1
  111. package/examples/check-accessibility.sh +0 -0
  112. package/examples/check-aria-labels.sh +0 -0
  113. package/examples/check-before-act-enforcer.sh +12 -0
  114. package/examples/check-charset-meta.sh +0 -0
  115. package/examples/check-cookie-flags.sh +0 -0
  116. package/examples/check-cors-config.sh +0 -0
  117. package/examples/check-csp-headers.sh +0 -0
  118. package/examples/check-csrf-protection.sh +0 -0
  119. package/examples/check-debounce.sh +1 -1
  120. package/examples/check-dependency-age.sh +0 -0
  121. package/examples/check-dependency-license.sh +0 -0
  122. package/examples/check-dockerfile-best-practice.sh +0 -0
  123. package/examples/check-error-boundaries.sh +0 -0
  124. package/examples/check-error-class.sh +1 -1
  125. package/examples/check-error-handling.sh +0 -0
  126. package/examples/check-error-logging.sh +1 -1
  127. package/examples/check-error-message.sh +0 -0
  128. package/examples/check-error-stack.sh +0 -0
  129. package/examples/check-favicon.sh +0 -0
  130. package/examples/check-git-hooks-compat.sh +0 -0
  131. package/examples/check-gitattributes.sh +0 -0
  132. package/examples/check-https-redirect.sh +0 -0
  133. package/examples/check-input-validation.sh +0 -0
  134. package/examples/check-lang-attribute.sh +0 -0
  135. package/examples/check-npm-scripts-exist.sh +0 -0
  136. package/examples/check-package-size.sh +0 -0
  137. package/examples/check-port-availability.sh +0 -0
  138. package/examples/check-promise-all.sh +1 -1
  139. package/examples/check-rate-limiting.sh +0 -0
  140. package/examples/check-return-types.sh +0 -0
  141. package/examples/check-semantic-versioning.sh +0 -0
  142. package/examples/check-suspense-fallback.sh +1 -1
  143. package/examples/check-test-exists.sh +0 -0
  144. package/examples/check-test-naming.sh +0 -0
  145. package/examples/check-timeout-cleanup.sh +1 -1
  146. package/examples/check-tls-version.sh +0 -0
  147. package/examples/check-unsubscribe.sh +1 -1
  148. package/examples/check-viewport-meta.sh +0 -0
  149. package/examples/check-worker-terminate.sh +1 -1
  150. package/examples/checkpoint-tamper-guard.sh +12 -0
  151. package/examples/chmod-guard.sh +12 -0
  152. package/examples/chown-guard.sh +24 -0
  153. package/examples/ci-workflow-guard.sh +6 -1
  154. package/examples/claim-verify-detector.sh +109 -0
  155. package/examples/claim-vs-caveat-checker.sh +77 -0
  156. package/examples/classifier-fallback-allow.sh +114 -40
  157. package/examples/claude-cache-gc.sh +1 -0
  158. package/examples/claude-code-version-pin-advisor.sh +183 -0
  159. package/examples/claude-md-reinjector.sh +129 -0
  160. package/examples/claude-md-size-monitor.sh +66 -0
  161. package/examples/claude-update-budget-guard.sh +123 -0
  162. package/examples/claude-update-smart.sh +113 -0
  163. package/examples/claudeignore-enforce-guard.sh +12 -0
  164. package/examples/claudemd-enforcer.sh +0 -0
  165. package/examples/claudemd-tool-prohibition.sh +128 -0
  166. package/examples/clear-command-confirm-guard.sh +32 -15
  167. package/examples/cli-config-pinning-detector.sh +162 -0
  168. package/examples/cliff-countdown-advisor.sh +96 -0
  169. package/examples/clipboard-secret-guard.sh +12 -0
  170. package/examples/closure-word-verify-gate.sh +150 -0
  171. package/examples/cloud-cli-guard.sh +39 -2
  172. package/examples/commit-all-scope-guard.sh +44 -0
  173. package/examples/commit-message-check.sh +1 -1
  174. package/examples/commit-message-quality.sh +6 -1
  175. package/examples/commitment-carry-forward-arrest.sh +361 -0
  176. package/examples/compact-alert-notification.sh +0 -0
  177. package/examples/compact-circuit-breaker.sh +72 -0
  178. package/examples/compact-dispatch-watchdog.sh +149 -0
  179. package/examples/completion-claim-without-verification-detector.sh +207 -0
  180. package/examples/composer-guard.sh +12 -0
  181. package/examples/compound-bash-permission-resolver.sh +156 -0
  182. package/examples/compound-command-allow.sh +1 -1
  183. package/examples/compound-command-deny-enforcer.sh +183 -0
  184. package/examples/compound-inject-guard.sh +12 -0
  185. package/examples/concurrent-edit-lock.sh +12 -0
  186. package/examples/conflict-marker-guard.sh +12 -0
  187. package/examples/consecutive-error-breaker.sh +0 -0
  188. package/examples/console-log-count.sh +1 -0
  189. package/examples/context-compact-advisor.sh +29 -2
  190. package/examples/context-length-budget.sh +69 -0
  191. package/examples/context-threshold-alert.sh +12 -0
  192. package/examples/context-usage-drift-alert.sh +41 -13
  193. package/examples/conversation-history-guard.sh +12 -0
  194. package/examples/core-file-protect-guard.sh +12 -0
  195. package/examples/cors-star-warn.sh +0 -0
  196. package/examples/cost-incident-self-audit.sh +162 -0
  197. package/examples/cowork-claude-md-load-checker.sh +100 -0
  198. package/examples/cowork-fuse-staleness-watcher.sh +140 -0
  199. package/examples/cowork-hook-absence-warner.sh +167 -0
  200. package/examples/cowork-model-picker-advisor.sh +115 -0
  201. package/examples/credential-exfil-guard.sh +65 -4
  202. package/examples/credential-file-cat-guard.sh +17 -1
  203. package/examples/cron-create-receipt.sh +112 -0
  204. package/examples/cron-modification-guard.sh +12 -0
  205. package/examples/cross-product-mcp-spawn-detector.sh +178 -0
  206. package/examples/cwd-project-boundary-guard.sh +0 -0
  207. package/examples/daemon-zombie-worker-surfacer.sh +118 -0
  208. package/examples/daily-cost-guard.sh +164 -0
  209. package/examples/daily-usage-tracker.sh +0 -0
  210. package/examples/dangerous-pip-flag-guard.sh +12 -0
  211. package/examples/db-connect-guard.sh +13 -1
  212. package/examples/denied-action-retry-guard.sh +12 -0
  213. package/examples/deny-bypass-detector.sh +12 -0
  214. package/examples/deny-rule-integrity-verifier.sh +181 -0
  215. package/examples/dependency-install-guard.sh +12 -0
  216. package/examples/deploy-guard.sh +14 -2
  217. package/examples/deploy-path-verify-guard.sh +12 -0
  218. package/examples/deployment-readback-gate.sh +135 -0
  219. package/examples/deployment-readback-gh-adapter.sh +247 -0
  220. package/examples/deployment-verify-guard.sh +25 -2
  221. package/examples/destructive-db-script-write-guard.sh +166 -0
  222. package/examples/destructive-migration-write-guard.sh +163 -0
  223. package/examples/diff-size-guard.sh +12 -0
  224. package/examples/disabled-feature-toggle-advisor.sh +88 -0
  225. package/examples/disk-partition-guard.sh +12 -0
  226. package/examples/dispatch-allowlist-preflight.sh +301 -0
  227. package/examples/dispatch-liveness-watchdog.sh +216 -0
  228. package/examples/dispatch-receipt.sh +174 -0
  229. package/examples/django-migrate-guard.sh +12 -0
  230. package/examples/dns-config-guard.sh +12 -0
  231. package/examples/docker-dangerous-guard.sh +12 -0
  232. package/examples/docker-volume-guard.sh +0 -0
  233. package/examples/dockerfile-latest-guard.sh +1 -0
  234. package/examples/dotenv-anthropic-key-billing-guard.sh +99 -0
  235. package/examples/dotenv-commit-guard.sh +12 -0
  236. package/examples/dotenv-read-guard.sh +12 -0
  237. package/examples/dotfile-protection-guard.sh +12 -0
  238. package/examples/dotnet-build-on-edit.sh +1 -1
  239. package/examples/drizzle-migrate-guard.sh +27 -2
  240. package/examples/echo-probe-spam-detector.sh +176 -0
  241. package/examples/edit-counter-test-gate.sh +12 -0
  242. package/examples/edit-error-counter.sh +1 -1
  243. package/examples/edit-guard.sh +12 -0
  244. package/examples/edit-old-string-validator.sh +12 -0
  245. package/examples/edit-quote-ambiguity-guard.sh +97 -0
  246. package/examples/edit-retry-loop-guard.sh +0 -0
  247. package/examples/edit-verify.sh +0 -0
  248. package/examples/env-inline-secret-guard.sh +14 -2
  249. package/examples/env-naming-convention.sh +0 -0
  250. package/examples/env-prod-guard.sh +0 -0
  251. package/examples/env-required-check.sh +0 -0
  252. package/examples/env-source-guard.sh +12 -0
  253. package/examples/env-var-check.sh +24 -1
  254. package/examples/ephemeral-container-detector.sh +147 -0
  255. package/examples/error-memory-guard.sh +12 -0
  256. package/examples/evidence-claim-gate.sh +187 -0
  257. package/examples/exploration-budget-guard.sh +89 -0
  258. package/examples/expo-eject-guard.sh +13 -0
  259. package/examples/extended-thinking-loop-guard.sh +139 -0
  260. package/examples/extended-thinking-resume-warning.sh +119 -0
  261. package/examples/extended-thinking-tool-use-mismatch-detector.sh +212 -0
  262. package/examples/fabricated-command-detector.sh +145 -0
  263. package/examples/false-disk-full-guard.sh +63 -0
  264. package/examples/feature-deprecation-detector.sh +109 -0
  265. package/examples/file-change-tracker.sh +1 -1
  266. package/examples/file-change-undo-tracker.sh +0 -0
  267. package/examples/file-edit-backup.sh +63 -14
  268. package/examples/file-reference-check.sh +0 -0
  269. package/examples/file-size-limit.sh +12 -0
  270. package/examples/financial-operation-guard.sh +12 -0
  271. package/examples/firewall-guard.sh +12 -0
  272. package/examples/fish-shell-wrapper.sh +125 -7
  273. package/examples/five-hundred-milestone.sh +1 -0
  274. package/examples/flask-static-route-guard.sh +89 -0
  275. package/examples/forbidden-response-phrase-detector.sh +161 -0
  276. package/examples/gem-push-guard.sh +13 -0
  277. package/examples/gh-cli-destructive-guard.sh +13 -1
  278. package/examples/git-checkout-safety-guard.sh +12 -0
  279. package/examples/git-checkout-uncommitted-guard.sh +12 -0
  280. package/examples/git-config-guard.sh +12 -0
  281. package/examples/git-crypt-worktree-guard.sh +12 -0
  282. package/examples/git-filter-repo-guard.sh +56 -0
  283. package/examples/git-history-rewrite-guard.sh +12 -0
  284. package/examples/git-hook-bypass-guard.sh +0 -0
  285. package/examples/git-maintenance-guard.sh +83 -0
  286. package/examples/git-merge-conflict-prevent.sh +0 -0
  287. package/examples/git-message-length-check.sh +0 -0
  288. package/examples/git-message-length.sh +0 -0
  289. package/examples/git-operations-require-approval.sh +68 -14
  290. package/examples/git-pack-temp-cleanup-guard.sh +102 -0
  291. package/examples/git-push-blast-radius-guard.sh +218 -0
  292. package/examples/git-remote-guard.sh +24 -3
  293. package/examples/git-rm-orphan-wipe-guard.sh +85 -0
  294. package/examples/git-stash-before-checkout.sh +12 -0
  295. package/examples/git-stash-before-danger.sh +0 -0
  296. package/examples/git-submodule-guard.sh +69 -2
  297. package/examples/git-tag-guard.sh +12 -0
  298. package/examples/github-actions-secret-guard.sh +0 -0
  299. package/examples/gitignore-check.sh +0 -0
  300. package/examples/gitops-drift-guard.sh +12 -0
  301. package/examples/go-mod-tidy-warn.sh +1 -0
  302. package/examples/go-vet-after-edit.sh +12 -0
  303. package/examples/goal-iteration-limit-warner.sh +152 -0
  304. package/examples/grep-nul-false-negative-guard.sh +30 -0
  305. package/examples/growthbook-flag-monitor.sh +257 -0
  306. package/examples/hallucination-url-check.sh +1 -1
  307. package/examples/halt-signal-detector.sh +135 -0
  308. package/examples/handoff-on-clear.sh +65 -0
  309. package/examples/hardcoded-ip-guard.sh +1 -0
  310. package/examples/headless-empty-result-guard.sh +0 -0
  311. package/examples/headless-stop-guard.sh +0 -0
  312. package/examples/helm-install-guard.sh +2 -1
  313. package/examples/home-critical-bash-guard.sh +17 -1
  314. package/examples/hook-debug-wrapper.sh +6 -2
  315. package/examples/hook-permission-fixer.sh +0 -0
  316. package/examples/hook-self-disable-detector.sh +99 -0
  317. package/examples/hook-stdout-sanitizer.sh +6 -2
  318. package/examples/hook-tamper-guard.sh +12 -0
  319. package/examples/idle-session-cost-alert.sh +0 -0
  320. package/examples/image-dimension-guard.sh +109 -0
  321. package/examples/image-file-validator.sh +0 -0
  322. package/examples/iteration-quality-degradation-detector.sh +170 -0
  323. package/examples/java-compile-on-edit.sh +1 -1
  324. package/examples/json-syntax-check.sh +0 -0
  325. package/examples/k8s-production-guard.sh +13 -1
  326. package/examples/kill-process-guard.sh +12 -0
  327. package/examples/kubernetes-guard.sh +13 -1
  328. package/examples/laravel-artisan-guard.sh +13 -0
  329. package/examples/large-file-guard.sh +1 -1
  330. package/examples/log-level-guard.sh +0 -0
  331. package/examples/log-truncation-guard.sh +12 -0
  332. package/examples/long-session-malformed-tool-call-detector.sh +183 -0
  333. package/examples/loop-detector.sh +12 -0
  334. package/examples/magic-number-warn.sh +1 -0
  335. package/examples/main-branch-warn.sh +12 -0
  336. package/examples/markdown-link-check.sh +0 -0
  337. package/examples/max-concurrent-agents.sh +12 -0
  338. package/examples/max-edit-size-guard.sh +13 -0
  339. package/examples/max-file-count-guard.sh +0 -0
  340. package/examples/max-file-delete-count.sh +0 -0
  341. package/examples/max-function-length.sh +1 -0
  342. package/examples/max-import-count.sh +0 -0
  343. package/examples/max-subagent-count.sh +0 -0
  344. package/examples/mcp-config-freeze.sh +12 -0
  345. package/examples/mcp-config-poisoning-audit.sh +150 -0
  346. package/examples/mcp-data-boundary.sh +1 -1
  347. package/examples/mcp-misdiagnosis-arrest.sh +209 -0
  348. package/examples/mcp-orphan-leak-warner.sh +49 -0
  349. package/examples/mcp-permissions-ask-warner.sh +151 -0
  350. package/examples/mcp-routine-approval-detector.sh +154 -0
  351. package/examples/mcp-server-allowlist.sh +12 -0
  352. package/examples/mcp-server-guard.sh +12 -0
  353. package/examples/mcp-startup-bloat-detector.sh +87 -0
  354. package/examples/mcp-stdio-compatibility-test.sh +153 -0
  355. package/examples/mcp-tool-audit-log.sh +0 -0
  356. package/examples/mcp-tool-guard.sh +101 -1
  357. package/examples/mcp-warmup-wait.sh +0 -0
  358. package/examples/memory-chain-audit.sh +56 -0
  359. package/examples/memory-orphan-detector.sh +188 -0
  360. package/examples/memory-write-guard.sh +99 -17
  361. package/examples/migration-verify-guard.sh +12 -0
  362. package/examples/model-swap-suggester.sh +177 -0
  363. package/examples/model-version-alert.sh +5 -1
  364. package/examples/model-version-lock.sh +63 -0
  365. package/examples/move-delete-sequence-guard.sh +33 -2
  366. package/examples/multi-file-plan-routing-gate.sh +192 -0
  367. package/examples/multi-vendor-concurrent-warner.sh +108 -0
  368. package/examples/multi-window-auth-drift-detector.sh +183 -0
  369. package/examples/multiline-command-approver.sh +161 -23
  370. package/examples/nested-background-agent-guard.sh +109 -0
  371. package/examples/nested-spawn-inflight-guard.sh +178 -0
  372. package/examples/network-exfil-guard.sh +12 -0
  373. package/examples/network-guard.sh +12 -0
  374. package/examples/network-interface-guard.sh +12 -0
  375. package/examples/nextjs-env-guard.sh +1 -1
  376. package/examples/no-absolute-import.sh +0 -0
  377. package/examples/no-alert-confirm-prompt.sh +0 -0
  378. package/examples/no-anonymous-default-export.sh +0 -0
  379. package/examples/no-any-type.sh +0 -0
  380. package/examples/no-any-typescript.sh +1 -0
  381. package/examples/no-ask-human.sh +12 -0
  382. package/examples/no-assignment-in-condition.sh +0 -0
  383. package/examples/no-base64-exfil.sh +12 -0
  384. package/examples/no-callback-hell.sh +0 -0
  385. package/examples/no-circular-dependency.sh +0 -0
  386. package/examples/no-cleartext-storage.sh +0 -0
  387. package/examples/no-commented-code.sh +0 -0
  388. package/examples/no-commit-fixup.sh +0 -0
  389. package/examples/no-console-assert.sh +0 -0
  390. package/examples/no-console-error-swallow.sh +0 -0
  391. package/examples/no-console-in-prod.sh +0 -0
  392. package/examples/no-console-log-commit.sh +12 -0
  393. package/examples/no-console-log.sh +0 -0
  394. package/examples/no-console-time.sh +0 -0
  395. package/examples/no-cors-wildcard.sh +4 -1
  396. package/examples/no-curl-upload.sh +0 -0
  397. package/examples/no-dangerouslySetInnerHTML.sh +0 -0
  398. package/examples/no-dangling-await.sh +1 -0
  399. package/examples/no-debug-commit.sh +12 -0
  400. package/examples/no-debug-in-commit.sh +0 -0
  401. package/examples/no-deep-nesting.sh +0 -0
  402. package/examples/no-deep-relative-import.sh +1 -0
  403. package/examples/no-default-credentials.sh +0 -0
  404. package/examples/no-deploy-friday.sh +13 -1
  405. package/examples/no-disabled-test.sh +0 -0
  406. package/examples/no-document-write.sh +0 -0
  407. package/examples/no-empty-function.sh +0 -0
  408. package/examples/no-eval-in-template.sh +0 -0
  409. package/examples/no-eval-template.sh +3 -1
  410. package/examples/no-eval.sh +0 -0
  411. package/examples/no-exec-user-input.sh +0 -0
  412. package/examples/no-fixme-ship.sh +12 -0
  413. package/examples/no-floating-promises.sh +0 -0
  414. package/examples/no-force-flag.sh +22 -5
  415. package/examples/no-force-install.sh +0 -0
  416. package/examples/no-git-amend.sh +12 -0
  417. package/examples/no-git-rebase-public.sh +0 -0
  418. package/examples/no-global-install.sh +12 -0
  419. package/examples/no-global-state.sh +0 -0
  420. package/examples/no-hardcoded-port.sh +1 -0
  421. package/examples/no-hardcoded-url.sh +0 -0
  422. package/examples/no-helmet-missing.sh +0 -0
  423. package/examples/no-http-url.sh +1 -0
  424. package/examples/no-http-without-https.sh +0 -0
  425. package/examples/no-inline-style.sh +0 -0
  426. package/examples/no-inline-styles.sh +1 -0
  427. package/examples/no-innerhtml.sh +0 -0
  428. package/examples/no-install-global.sh +12 -0
  429. package/examples/no-jwt-in-url.sh +0 -0
  430. package/examples/no-large-commit.sh +0 -0
  431. package/examples/no-localhost-expose.sh +0 -0
  432. package/examples/no-magic-number.sh +0 -0
  433. package/examples/no-md5-sha1.sh +0 -0
  434. package/examples/no-mixed-line-endings.sh +8 -1
  435. package/examples/no-mutation-in-reducer.sh +0 -0
  436. package/examples/no-nested-ternary.sh +0 -0
  437. package/examples/no-network-exfil.sh +0 -0
  438. package/examples/no-open-redirect.sh +0 -0
  439. package/examples/no-output-truncation.sh +12 -0
  440. package/examples/no-package-downgrade.sh +0 -0
  441. package/examples/no-package-lock-edit.sh +12 -0
  442. package/examples/no-path-join-user-input.sh +0 -0
  443. package/examples/no-port-bind.sh +0 -0
  444. package/examples/no-process-exit.sh +0 -0
  445. package/examples/no-prototype-pollution.sh +0 -0
  446. package/examples/no-push-without-ci.sh +0 -0
  447. package/examples/no-push-without-tests.sh +12 -0
  448. package/examples/no-raw-password-in-url.sh +0 -0
  449. package/examples/no-root-user-docker.sh +1 -0
  450. package/examples/no-root-write.sh +12 -0
  451. package/examples/no-secrets-in-args.sh +4 -1
  452. package/examples/no-secrets-in-logs.sh +0 -0
  453. package/examples/no-sensitive-log.sh +0 -0
  454. package/examples/no-sleep-in-hooks.sh +0 -0
  455. package/examples/no-star-import-python.sh +1 -0
  456. package/examples/no-string-concat-sql.sh +0 -0
  457. package/examples/no-sudo-guard.sh +12 -0
  458. package/examples/no-sync-fs.sh +0 -0
  459. package/examples/no-todo-in-merge.sh +0 -0
  460. package/examples/no-todo-in-production.sh +1 -0
  461. package/examples/no-todo-without-issue.sh +0 -0
  462. package/examples/no-unused-import.sh +0 -0
  463. package/examples/no-var-keyword.sh +0 -0
  464. package/examples/no-verify-blocker.sh +12 -0
  465. package/examples/no-wget-piped-bash.sh +12 -0
  466. package/examples/no-wildcard-cors.sh +0 -0
  467. package/examples/no-wildcard-delete.sh +0 -0
  468. package/examples/no-wildcard-import.sh +0 -0
  469. package/examples/no-with-statement.sh +0 -0
  470. package/examples/no-write-outside-src.sh +0 -0
  471. package/examples/no-xml-external-entity.sh +0 -0
  472. package/examples/non-english-quality-warner.sh +156 -0
  473. package/examples/notify-waiting.sh +1 -1
  474. package/examples/npm-audit-warn.sh +0 -0
  475. package/examples/npm-global-install-guard.sh +12 -0
  476. package/examples/npm-publish-guard.sh +12 -0
  477. package/examples/npm-script-injection.sh +0 -0
  478. package/examples/npm-supply-chain-guard.sh +0 -0
  479. package/examples/nuxt-config-guard.sh +1 -0
  480. package/examples/oauth-refresh-monitor.sh +210 -0
  481. package/examples/opus-degradation-tracker.sh +187 -0
  482. package/examples/opus48-routine-task-warning.sh +196 -0
  483. package/examples/opus48-thinking-wedge-advisor.sh +143 -0
  484. package/examples/output-credential-scan.sh +1 -1
  485. package/examples/output-secret-mask.sh +31 -9
  486. package/examples/output-token-spike-detector.sh +145 -0
  487. package/examples/package-json-guard.sh +12 -0
  488. package/examples/package-lock-frozen.sh +12 -0
  489. package/examples/parallel-batch-size-limiter.sh +121 -0
  490. package/examples/parallel-cascade-detector.sh +116 -0
  491. package/examples/partial-view-claim-arrest.sh +174 -0
  492. package/examples/path-deny-bash-guard.sh +12 -0
  493. package/examples/path-traversal-guard.sh +12 -0
  494. package/examples/per-prompt-token-cap.sh +124 -0
  495. package/examples/permission-audit-log.sh +1 -1
  496. package/examples/permission-denial-enforcer.sh +12 -0
  497. package/examples/permission-entry-validator.sh +0 -0
  498. package/examples/persisted-1m-model-advisor.sh +88 -0
  499. package/examples/php-lint-on-edit.sh +1 -1
  500. package/examples/pii-upload-guard.sh +12 -0
  501. package/examples/pip-publish-guard.sh +13 -0
  502. package/examples/pip-requirements-guard.sh +12 -0
  503. package/examples/pip-venv-required.sh +12 -0
  504. package/examples/plan-mode-edit-guard.sh +12 -0
  505. package/examples/plan-mode-enforcer.sh +12 -0
  506. package/examples/plan-mode-strict-guard.sh +12 -0
  507. package/examples/plugin-hooks-json-bloat-detector.sh +169 -0
  508. package/examples/plugin-process-cleanup.sh +0 -0
  509. package/examples/polyglot-rm-guard.sh +12 -0
  510. package/examples/post-compact-safety.sh +12 -0
  511. package/examples/post-edit-disk-verify.sh +152 -0
  512. package/examples/powershell-remove-item-guard.sh +85 -0
  513. package/examples/pr-description-check.sh +0 -0
  514. package/examples/pr-duplicate-guard.sh +13 -0
  515. package/examples/pre-bash-sed-line-ending-windows.sh +87 -0
  516. package/examples/pre-compact-knowledge-save.sh +0 -0
  517. package/examples/pre-compact-transcript-backup.sh +0 -0
  518. package/examples/pre-execution-claim-detector.sh +179 -0
  519. package/examples/prefer-builtin-tools.sh +10 -1
  520. package/examples/prefer-const.sh +0 -0
  521. package/examples/prefer-dedicated-tools.sh +12 -0
  522. package/examples/prefer-optional-chaining.sh +0 -0
  523. package/examples/prisma-migrate-guard.sh +24 -7
  524. package/examples/production-port-kill-guard.sh +12 -0
  525. package/examples/prompt-injection-guard.sh +2 -1
  526. package/examples/prompt-usage-logger.sh +0 -0
  527. package/examples/protect-claudemd.sh +12 -0
  528. package/examples/protect-dotfiles.sh +12 -0
  529. package/examples/proxy-capture-suggester.sh +159 -0
  530. package/examples/public-artefact-socratic-narrowing.sh +232 -0
  531. package/examples/public-repo-push-guard.sh +12 -0
  532. package/examples/push-requires-test-pass-record.sh +0 -0
  533. package/examples/push-requires-test-pass.sh +12 -0
  534. package/examples/quota-anomaly-detector.sh +173 -0
  535. package/examples/quota-reset-audit.sh +58 -0
  536. package/examples/quoted-flag-approver.sh +99 -10
  537. package/examples/rails-migration-guard.sh +12 -0
  538. package/examples/rate-limit-guard.sh +0 -0
  539. package/examples/read-all-files-enforcer.sh +0 -0
  540. package/examples/read-budget-guard.sh +12 -0
  541. package/examples/read-loop-detector.sh +59 -0
  542. package/examples/read-once-guard.sh +96 -0
  543. package/examples/read-only-mode.sh +12 -0
  544. package/examples/readme-exists-check.sh +0 -0
  545. package/examples/record-read-coverage.sh +73 -0
  546. package/examples/redirect-fragment-warner.sh +149 -0
  547. package/examples/redis-flushall-guard.sh +13 -0
  548. package/examples/redundant-read-blocker.sh +132 -0
  549. package/examples/refusal-arrest-gate.sh +248 -0
  550. package/examples/registry-publish-guard.sh +13 -1
  551. package/examples/remote-control-billing-classifier.sh +135 -0
  552. package/examples/replace-all-guard.sh +12 -0
  553. package/examples/repo-visibility-guard.sh +12 -0
  554. package/examples/reroute-after-block-guard.sh +150 -0
  555. package/examples/response-budget-guard.sh +0 -0
  556. package/examples/resume-drift-watcher.sh +57 -0
  557. package/examples/rg-replace-flag-detector.sh +125 -0
  558. package/examples/rhetorical-verification-prompt-detector.sh +102 -0
  559. package/examples/ripgrep-permission-fix.sh +0 -0
  560. package/examples/rm-safety-net.sh +151 -8
  561. package/examples/role-tool-guard.sh +12 -0
  562. package/examples/route-handler-emptiness-gate.sh +324 -0
  563. package/examples/ruby-lint-on-edit.sh +1 -1
  564. package/examples/runtime-binary-change-detector.sh +102 -0
  565. package/examples/same-command-repeat-detector.sh +196 -0
  566. package/examples/same-correction-arrest.sh +169 -0
  567. package/examples/sandbox-denywrite-enforcer.sh +78 -0
  568. package/examples/sandbox-relative-path-audit.sh +83 -25
  569. package/examples/sandbox-write-verify.sh +12 -0
  570. package/examples/schema-migration-guard.sh +0 -0
  571. package/examples/scope-expansion-receipt.sh +178 -0
  572. package/examples/scope-guard.sh +88 -9
  573. package/examples/secret-file-read-guard.sh +12 -0
  574. package/examples/secret-file-write-guard.sh +150 -0
  575. package/examples/self-modify-bypass-guard.sh +0 -0
  576. package/examples/sensitive-file-read-guard.sh +23 -3
  577. package/examples/sensitive-log-guard.sh +1 -0
  578. package/examples/server-side-prompt-injection-detector.sh +69 -0
  579. package/examples/session-agent-cost-limiter.sh +12 -0
  580. package/examples/session-backup-on-start.sh +1 -1
  581. package/examples/session-cost-alert.sh +12 -0
  582. package/examples/session-drift-guard.sh +12 -0
  583. package/examples/session-duration-guard.sh +25 -2
  584. package/examples/session-end-logger.sh +0 -0
  585. package/examples/session-health-monitor.sh +0 -0
  586. package/examples/session-index-repair.sh +1 -1
  587. package/examples/session-memory-watchdog.sh +1 -0
  588. package/examples/session-permission-reset-guard.sh +12 -0
  589. package/examples/session-persistence-verifier.sh +93 -0
  590. package/examples/session-plugin-pin-watch.sh +68 -0
  591. package/examples/session-rate-monitor.sh +176 -0
  592. package/examples/session-resume-env-fix.sh +0 -0
  593. package/examples/session-start-quota-status.sh +193 -0
  594. package/examples/session-start-safety-check.sh +55 -3
  595. package/examples/session-state-saver.sh +0 -0
  596. package/examples/session-summary-stop.sh +1 -1
  597. package/examples/session-summary.sh +0 -0
  598. package/examples/session-token-counter.sh +1 -1
  599. package/examples/settings-hooks-key-restorer.sh +99 -0
  600. package/examples/settings-json-health-check.sh +57 -0
  601. package/examples/settings-json-model-guard.sh +0 -0
  602. package/examples/settings-regression-tester.sh +188 -0
  603. package/examples/shell-config-truncation-guard.sh +12 -0
  604. package/examples/shell-wrapper-guard.sh +12 -0
  605. package/examples/skill-cumulative-size-detector.sh +104 -0
  606. package/examples/skill-description-drop-detector.sh +148 -0
  607. package/examples/skill-gate.sh +0 -0
  608. package/examples/skill-truncation-detector.sh +154 -0
  609. package/examples/skills-context-recorder.sh +167 -0
  610. package/examples/skills-load-verifier.sh +96 -0
  611. package/examples/skills-settings-validator.sh +139 -0
  612. package/examples/sonnet-45-deprecation-helper.sh +85 -0
  613. package/examples/spec-file-scope-guard.sh +12 -0
  614. package/examples/spring-profile-guard.sh +1 -0
  615. package/examples/spurious-malformed-notice-detector.sh +247 -0
  616. package/examples/sql-bulk-delete-warn.sh +88 -0
  617. package/examples/sql-injection-detect.sh +0 -0
  618. package/examples/ssh-key-protect.sh +12 -0
  619. package/examples/staged-secret-scan.sh +22 -1
  620. package/examples/stale-temp-settings-detector.sh +86 -0
  621. package/examples/standing-rule-session-surfacer.sh +137 -0
  622. package/examples/stop-hook-sigterm-wrapper.sh +182 -0
  623. package/examples/stop-transcript-write-health.sh +64 -0
  624. package/examples/strict-allowlist.sh +57 -15
  625. package/examples/strip-coauthored-by.sh +50 -10
  626. package/examples/subagent-blast-radius-guard.sh +184 -0
  627. package/examples/subagent-boundary-precheck.sh +126 -0
  628. package/examples/subagent-budget-guard.sh +12 -0
  629. package/examples/subagent-claudemd-inject.sh +0 -0
  630. package/examples/subagent-closure-verify-gate.sh +164 -0
  631. package/examples/subagent-destructive-git-guard.sh +120 -0
  632. package/examples/subagent-error-detector.sh +0 -0
  633. package/examples/subagent-forged-system-reminder-guard.sh +156 -0
  634. package/examples/subagent-identity-leak-guard.sh +102 -0
  635. package/examples/subagent-identity-reassertion.sh +51 -0
  636. package/examples/subagent-inheritance-tester.sh +179 -0
  637. package/examples/subagent-permission-mode-guard.sh +110 -0
  638. package/examples/subagent-scope-guard.sh +12 -0
  639. package/examples/subagent-spawn-verification-enforcer.sh +102 -0
  640. package/examples/subagent-tool-allowlist-enforcer.sh +101 -0
  641. package/examples/subagent-tool-call-limiter.sh +87 -15
  642. package/examples/subcommand-chain-guard.sh +12 -0
  643. package/examples/subscription-api-billing-warner.sh +160 -0
  644. package/examples/subscription-bypass-detector.sh +152 -0
  645. package/examples/svelte-lint-on-edit.sh +1 -0
  646. package/examples/swift-build-on-edit.sh +1 -1
  647. package/examples/symlink-guard.sh +27 -2
  648. package/examples/symlink-protect.sh +1 -0
  649. package/examples/system-dir-protection-guard.sh +73 -8
  650. package/examples/system-message-workaround.sh +38 -13
  651. package/examples/system-package-guard.sh +12 -0
  652. package/examples/systemd-service-guard.sh +12 -0
  653. package/examples/task-integrity-guard.sh +12 -0
  654. package/examples/temp-file-cleanup.sh +1 -1
  655. package/examples/temporal-suggestion-detector.sh +135 -0
  656. package/examples/terraform-guard.sh +27 -6
  657. package/examples/test-after-edit.sh +1 -1
  658. package/examples/test-before-push.sh +12 -0
  659. package/examples/test-coverage-reminder.sh +24 -1
  660. package/examples/thinking-budget-effort-mismatch-detector.sh +149 -0
  661. package/examples/thinking-stall-detector.sh +61 -0
  662. package/examples/timezone-guard.sh +0 -0
  663. package/examples/tmp-output-size-guard.sh +0 -0
  664. package/examples/todo-check.sh +1 -1
  665. package/examples/token-budget-guard.sh +12 -0
  666. package/examples/token-budget-per-task.sh +12 -0
  667. package/examples/token-usage-tracker.sh +7 -1
  668. package/examples/tokenizer-ratio-alert-corpus.sh +90 -0
  669. package/examples/tokenizer-ratio-alert.sh +104 -0
  670. package/examples/tool-call-rate-limiter.sh +0 -0
  671. package/examples/tool-result-correlation-checker.sh +167 -0
  672. package/examples/tool-result-size-guard.sh +132 -0
  673. package/examples/tool-retry-budget-guard.sh +12 -0
  674. package/examples/transcript-contamination-detector.sh +138 -0
  675. package/examples/trustfall-mcp-injection-guard.sh +103 -0
  676. package/examples/ultrareview-large-diff-advisor.sh +184 -0
  677. package/examples/unbounded-output-guard.sh +94 -0
  678. package/examples/uncommitted-changes-stop.sh +1 -0
  679. package/examples/uncommitted-discard-guard.sh +23 -5
  680. package/examples/uncommitted-work-guard.sh +12 -0
  681. package/examples/usage-warn.sh +0 -0
  682. package/examples/user-account-guard.sh +12 -0
  683. package/examples/userprompt-submit-receipt.sh +123 -0
  684. package/examples/variable-expansion-guard.sh +12 -0
  685. package/examples/verify-after-publish-reminder.sh +93 -0
  686. package/examples/verify-before-commit.sh +12 -0
  687. package/examples/version-bump-detector.sh +156 -0
  688. package/examples/version-regression-warner.sh +144 -0
  689. package/examples/vue-lint-on-edit.sh +1 -0
  690. package/examples/warn-cron-cost-trap.sh +173 -0
  691. package/examples/webfetch-runaway-guard.sh +89 -0
  692. package/examples/wellness-break-reminder.sh +118 -0
  693. package/examples/windows-destructive-command-guard.sh +177 -0
  694. package/examples/windows-path-guard.sh +12 -0
  695. package/examples/windows-python-stub-detector.sh +63 -0
  696. package/examples/work-hours-guard.sh +12 -0
  697. package/examples/working-directory-fence.sh +12 -0
  698. package/examples/workspace-lease-guard.sh +205 -0
  699. package/examples/worktree-create-log.sh +1 -0
  700. package/examples/worktree-delete-guard.sh +12 -0
  701. package/examples/worktree-edit-boundary-guard.sh +127 -0
  702. package/examples/worktree-escape-write-guard.sh +114 -0
  703. package/examples/worktree-hook-linker.sh +0 -0
  704. package/examples/worktree-hooks-path-fix.sh +111 -0
  705. package/examples/worktree-parent-write-guard.sh +43 -0
  706. package/examples/worktree-project-unify.sh +2 -1
  707. package/examples/worktree-remove-uncommitted-guard.sh +13 -0
  708. package/examples/worktree-unmerged-guard.sh +7 -1
  709. package/examples/write-byte-integrity-verifier.sh +190 -0
  710. package/examples/write-empty-content-guard.sh +67 -0
  711. package/examples/write-nul-corruption-detector.sh +61 -0
  712. package/examples/write-overwrite-confirm.sh +160 -14
  713. package/examples/write-secret-guard.sh +27 -5
  714. package/examples/write-shrink-guard.sh +12 -0
  715. package/examples/write-test-ratio.sh +0 -0
  716. package/examples/wsl-host-disk-space-guard.sh +97 -0
  717. package/examples/xml-format-leak-detector.sh +266 -0
  718. package/examples/yaml-syntax-check.sh +12 -0
  719. package/hooks/hooks.json +6 -6
  720. package/index.mjs +1699 -183
  721. package/mission.md +2 -0
  722. package/package.json +4 -4
  723. package/plugins/credential-guard/.claude-plugin/plugin.json +9 -7
  724. package/plugins/git-protection/.claude-plugin/plugin.json +10 -8
  725. package/plugins/safety-essentials/.claude-plugin/plugin.json +9 -7
  726. package/plugins/token-guard/.claude-plugin/plugin.json +10 -8
  727. package/scripts/agents-md-sync-setup.sh +156 -0
  728. package/scripts/autonomy-blocked-summary.sh +148 -0
  729. package/scripts/build-search-index.py +43 -0
  730. package/scripts/build-sitemap.py +119 -0
  731. package/scripts/cc-doctor.sh +192 -0
  732. package/scripts/check-hook-event-names.py +127 -0
  733. package/scripts/check-misfire-instrument.sh +64 -0
  734. package/scripts/claim-verify-audit.sh +467 -0
  735. package/scripts/cowork-claudemd-helper.sh +136 -0
  736. package/scripts/june-15-deprecated-model-scan.sh +111 -0
  737. package/scripts/measure-heredoc-shapes.sh +67 -0
  738. package/scripts/measure-literal-match-misfire.sh +110 -0
  739. package/scripts/probe-scope-guard-branches.sh +48 -0
  740. package/scripts/probe-skip-line-both-ways.sh +65 -0
  741. package/scripts/receipts-aggregate.py +199 -0
  742. package/scripts/session-forensic-audit.py +360 -0
  743. package/scripts.json +9 -9
  744. package/scripts.json.bak-2026-07-27-find +13 -0
  745. package/skills/safety-setup/SKILL.md +5 -5
  746. package/tests/approve-side-remaining-two.test.sh +129 -0
  747. package/tests/approver-list-granularity.test.sh +145 -0
  748. package/tests/askuserquestion-autonomy-gate.test.sh +181 -0
  749. package/tests/audit-ci-gate.test.sh +87 -0
  750. package/tests/audit-cross-layer-claudemd.test.sh +170 -0
  751. package/tests/audit-fail-open-parse.test.sh +100 -0
  752. package/tests/auto-approve-compound-tail.test.sh +194 -0
  753. package/tests/auto-mode-path-invoked-commands.test.sh +89 -0
  754. package/tests/auto-mode-quoted-targets.test.sh +127 -0
  755. package/tests/auto-mode-unquoted-targets.test.sh +112 -0
  756. package/tests/bash-secret-output-detector-detects.test.sh +102 -0
  757. package/tests/blindspots-cross-layer.test.sh +177 -0
  758. package/tests/block-database-wipe.test.sh +64 -0
  759. package/tests/bundled-short-flags-bypass.test.sh +85 -0
  760. package/tests/cd-git-allow-compound-tail.test.sh +67 -0
  761. package/tests/chown-guard-filesystem-root.test.sh +64 -0
  762. package/tests/ci-workflow-guard-skip-rule.test.sh +115 -0
  763. package/tests/compound-deny-safe-rm-targets.test.sh +105 -0
  764. package/tests/core-scripts-parser-fallback.test.sh +140 -0
  765. package/tests/destructive-guard-bare-glob.test.sh +74 -0
  766. package/tests/destructive-guard-every-operand.test.sh +100 -0
  767. package/tests/destructive-guard-find-deletion.test.sh +114 -0
  768. package/tests/destructive-guard-flag-order.test.sh +106 -0
  769. package/tests/destructive-guard-mentions-vs-invocations.test.sh +107 -0
  770. package/tests/destructive-guard-quoted-target.test.sh +89 -0
  771. package/tests/destructive-guard-separators.test.sh +105 -0
  772. package/tests/destructive-guard-variable-target.test.sh +98 -0
  773. package/tests/destructive-guard-wrapped-command.test.sh +91 -0
  774. package/tests/doctor-hook-disabling-env.test.sh +92 -0
  775. package/tests/doctor-misspelled-settings-keys.test.sh +106 -0
  776. package/tests/example-guards-wrapped-command.test.sh +169 -0
  777. package/tests/file-edit-backup.test.sh +93 -0
  778. package/tests/git-filter-repo-guard.test.sh +60 -0
  779. package/tests/git-global-options-bypass.test.sh +141 -0
  780. package/tests/git-invocation-prefixes-all-guards.test.sh +114 -0
  781. package/tests/git-maintenance-guard.test.sh +83 -0
  782. package/tests/git-pack-temp-cleanup-guard.test.sh +133 -0
  783. package/tests/git-rm-orphan-wipe-guard.test.sh +66 -0
  784. package/tests/git-submodule-guard.test.sh +50 -0
  785. package/tests/grep-pcre-portability.test.sh +155 -0
  786. package/tests/hook-registration-matches-input.test.sh +73 -0
  787. package/tests/hook-trigger-matches-envelope.test.sh +178 -0
  788. package/tests/install-does-not-claim-protection.test.sh +110 -0
  789. package/tests/install-example-standalone-tools.test.sh +139 -0
  790. package/tests/line-continuation-bypass.test.sh +114 -0
  791. package/tests/mcp-config-poisoning-audit.test.sh +106 -0
  792. package/tests/nested-background-agent-guard.test.sh +58 -0
  793. package/tests/no-unqualified-safety-claims.test.sh +114 -0
  794. package/tests/option-eating-grep-patterns.test.sh +130 -0
  795. package/tests/outdated-core-guards.test.sh +134 -0
  796. package/tests/outdated-report.test.sh +155 -0
  797. package/tests/output-secret-mask-warns.test.sh +73 -0
  798. package/tests/plugin-hooks-fail-open-under-sh.test.sh +165 -0
  799. package/tests/plugins-word-order.test.sh +126 -0
  800. package/tests/powershell-remove-item-guard.test.sh +85 -0
  801. package/tests/project-dir-naming.test.sh +103 -0
  802. package/tests/quoted-safe-targets-and-mentions.test.sh +190 -0
  803. package/tests/reroute-after-block-guard.test.sh +104 -0
  804. package/tests/secret-guard-documented-promises.test.sh +97 -0
  805. package/tests/session-plugin-pin-watch.test.sh +45 -0
  806. package/tests/settings-unreadable-refuses-to-write.test.sh +95 -0
  807. package/tests/shield-no-silent-adoption.test.py +110 -0
  808. package/tests/shield-no-silent-adoption.test.sh +46 -0
  809. package/tests/stop-transcript-write-health.test.sh +46 -0
  810. package/tests/system-dir-guard-root-erased.test.sh +66 -0
  811. package/tests/test-account-billing-log.sh +100 -0
  812. package/tests/test-account-routing-preflight.sh +77 -0
  813. package/tests/test-agent-sdk-credit-pool-monitor.sh +157 -0
  814. package/tests/test-agent-view-quota-warn.sh +184 -0
  815. package/tests/test-agents-md-edit-drift-warner.sh +176 -0
  816. package/tests/test-agents-md-loader.sh +204 -0
  817. package/tests/test-agents-md-sync-checker.sh +125 -0
  818. package/tests/test-ai-slop-punctuation-arrest.sh +280 -0
  819. package/tests/test-allowlist.sh +60 -0
  820. package/tests/test-always-allow-pattern-suggester.sh +147 -0
  821. package/tests/test-anthropic-base-url-guard.sh +88 -0
  822. package/tests/test-articulated-scope-capture.sh +139 -0
  823. package/tests/test-attachment-traversal-guard.sh +168 -0
  824. package/tests/test-aup-block-pattern-logger.sh +315 -0
  825. package/tests/test-aup-false-positive-helper.sh +188 -0
  826. package/tests/test-aup-large-tool-output-warner.sh +370 -0
  827. package/tests/test-aup-retry-loop-guard.sh +341 -0
  828. package/tests/test-auth-expiry-reminder.sh +303 -0
  829. package/tests/test-auth-macos-sleep-detector.sh +254 -0
  830. package/tests/test-auth-path-detector.sh +232 -0
  831. package/tests/test-auth-status-checker.sh +233 -0
  832. package/tests/test-authorized-reconfirmation-detector.sh +280 -0
  833. package/tests/test-background-cost-launch-guard.sh +62 -0
  834. package/tests/test-bash-allowlist-secondary-check.sh +143 -0
  835. package/tests/test-bash-fanout-bounded-rewriter.sh +186 -0
  836. package/tests/test-bash-project-fence.sh +127 -0
  837. package/tests/test-bg-permission-prompt-warner.sh +221 -0
  838. package/tests/test-binary-read-detector.sh +173 -0
  839. package/tests/test-broad-prefix-session-trap-warner.sh +167 -0
  840. package/tests/test-bulk-delete-target-resolution.sh +49 -0
  841. package/tests/test-bypass-mode-effective-verifier.sh +179 -0
  842. package/tests/test-cache-creation-drift-detector.sh +244 -0
  843. package/tests/test-cache-residue-detector.sh +429 -0
  844. package/tests/test-cache-tier-logger.sh +59 -0
  845. package/tests/test-cache-ttl-eviction-detector.sh +282 -0
  846. package/tests/test-cch-sentinel-precommit-guard.sh +64 -0
  847. package/tests/test-claim-verify-detector.sh +222 -0
  848. package/tests/test-claim-vs-caveat-checker.sh +134 -0
  849. package/tests/test-claude-code-version-pin-advisor.sh +353 -0
  850. package/tests/test-claude-md-reinjector.sh +173 -0
  851. package/tests/test-claude-md-size-monitor.sh +107 -0
  852. package/tests/test-claude-update-budget-guard.sh +132 -0
  853. package/tests/test-claude-update-smart.sh +91 -0
  854. package/tests/test-claudemd-tool-prohibition.sh +239 -0
  855. package/tests/test-cli-config-pinning-detector.sh +233 -0
  856. package/tests/test-cliff-countdown-advisor.sh +138 -0
  857. package/tests/test-closure-word-verify-gate.sh +158 -0
  858. package/tests/test-commit-all-scope-guard.sh +73 -0
  859. package/tests/test-commitment-carry-forward-arrest.sh +250 -0
  860. package/tests/test-compact-circuit-breaker.sh +134 -0
  861. package/tests/test-compact-dispatch-watchdog.sh +147 -0
  862. package/tests/test-completion-claim-without-verification-detector.sh +326 -0
  863. package/tests/test-compound-bash-permission-resolver.sh +264 -0
  864. package/tests/test-compound-command-deny-enforcer.sh +67 -0
  865. package/tests/test-context-length-budget.sh +68 -0
  866. package/tests/test-context-usage-drift-alert.sh +52 -22
  867. package/tests/test-cost-incident-self-audit.sh +94 -0
  868. package/tests/test-cowork-claude-md-load-checker.sh +257 -0
  869. package/tests/test-cowork-claudemd-helper.sh +141 -0
  870. package/tests/test-cowork-fuse-staleness-watcher.sh +287 -0
  871. package/tests/test-cowork-hook-absence-warner.sh +230 -0
  872. package/tests/test-cowork-model-picker-advisor.sh +317 -0
  873. package/tests/test-credential-exfil-guard.sh +62 -0
  874. package/tests/test-cron-create-receipt.sh +165 -0
  875. package/tests/test-cross-product-mcp-spawn-detector.sh +112 -0
  876. package/tests/test-daemon-zombie-worker-surfacer.sh +71 -0
  877. package/tests/test-daily-cost-guard.sh +131 -0
  878. package/tests/test-deny-rule-integrity-verifier.sh +288 -0
  879. package/tests/test-deployment-readback-gate.sh +92 -0
  880. package/tests/test-deployment-readback-gh-adapter.sh +163 -0
  881. package/tests/test-disabled-feature-toggle-advisor.sh +78 -0
  882. package/tests/test-dispatch-allowlist-preflight.sh +385 -0
  883. package/tests/test-dispatch-liveness-watchdog.sh +319 -0
  884. package/tests/test-dispatch-receipt.sh +314 -0
  885. package/tests/test-dotenv-anthropic-key-billing-guard.sh +160 -0
  886. package/tests/test-echo-probe-spam-detector.sh +143 -0
  887. package/tests/test-edit-quote-ambiguity-guard.sh +75 -0
  888. package/tests/test-ephemeral-container-detector.sh +251 -0
  889. package/tests/test-evidence-claim-gate.sh +291 -0
  890. package/tests/test-exploration-budget-guard.sh +164 -0
  891. package/tests/test-extended-thinking-loop-guard.sh +289 -0
  892. package/tests/test-extended-thinking-resume-warning.sh +240 -0
  893. package/tests/test-extended-thinking-tool-use-mismatch-detector.sh +236 -0
  894. package/tests/test-fabricated-command-detector.sh +296 -0
  895. package/tests/test-false-disk-full-guard.sh +36 -0
  896. package/tests/test-feature-deprecation-detector.sh +117 -0
  897. package/tests/test-forbidden-response-phrase-detector.sh +246 -0
  898. package/tests/test-git-operations-require-approval.sh +53 -0
  899. package/tests/test-git-push-blast-radius-guard.sh +115 -0
  900. package/tests/test-goal-iteration-limit-warner.sh +128 -0
  901. package/tests/test-growthbook-flag-monitor.sh +428 -0
  902. package/tests/test-halt-signal-detector.sh +120 -0
  903. package/tests/test-hook-self-disable-detector.sh +232 -0
  904. package/tests/test-iteration-quality-degradation-detector.sh +244 -0
  905. package/tests/test-long-session-malformed-tool-call-detector.sh +185 -0
  906. package/tests/test-marketplace-plugins.sh +193 -0
  907. package/tests/test-mcp-misdiagnosis-arrest.sh +235 -0
  908. package/tests/test-mcp-orphan-leak-warner.sh +71 -0
  909. package/tests/test-mcp-permissions-ask-warner.sh +207 -0
  910. package/tests/test-mcp-routine-approval-detector.sh +229 -0
  911. package/tests/test-mcp-startup-bloat-detector.sh +141 -0
  912. package/tests/test-mcp-stdio-compatibility-test.sh +112 -0
  913. package/tests/test-memory-chain-audit.sh +59 -0
  914. package/tests/test-memory-orphan-detector.sh +227 -0
  915. package/tests/test-model-swap-suggester.sh +368 -0
  916. package/tests/test-model-version-lock.sh +83 -0
  917. package/tests/test-multi-file-plan-routing-gate.sh +277 -0
  918. package/tests/test-multi-window-auth-drift-detector.sh +262 -0
  919. package/tests/test-nested-spawn-inflight-guard.sh +281 -0
  920. package/tests/test-no-force-flag.sh +49 -0
  921. package/tests/test-non-english-quality-warner.sh +229 -0
  922. package/tests/test-oauth-refresh-monitor.sh +311 -0
  923. package/tests/test-opus-degradation-tracker.sh +274 -0
  924. package/tests/test-opus48-routine-task-warning.sh +201 -0
  925. package/tests/test-opus48-thinking-wedge-advisor.sh +249 -0
  926. package/tests/test-output-token-spike-detector.sh +315 -0
  927. package/tests/test-parallel-batch-size-limiter.sh +228 -0
  928. package/tests/test-parallel-cascade-detector.sh +191 -0
  929. package/tests/test-partial-view-claim-arrest.sh +272 -0
  930. package/tests/test-per-prompt-token-cap.sh +136 -0
  931. package/tests/test-persisted-1m-model-advisor.sh +71 -0
  932. package/tests/test-plugin-hooks-json-bloat-detector.sh +267 -0
  933. package/tests/test-post-edit-disk-verify.sh +294 -0
  934. package/tests/test-pre-bash-sed-line-ending-windows.sh +108 -0
  935. package/tests/test-pre-execution-claim-detector.sh +366 -0
  936. package/tests/test-private-key-backup-and-git-credentials.sh +100 -0
  937. package/tests/test-proxy-capture-suggester.sh +214 -0
  938. package/tests/test-public-artefact-socratic-narrowing.sh +346 -0
  939. package/tests/test-quota-anomaly-detector.sh +321 -0
  940. package/tests/test-quota-reset-audit.sh +81 -0
  941. package/tests/test-read-loop-detector.sh +137 -0
  942. package/tests/test-read-once-guard.sh +85 -0
  943. package/tests/test-receipts-aggregate.sh +143 -0
  944. package/tests/test-redirect-fragment-warner.sh +130 -0
  945. package/tests/test-redundant-read-blocker.sh +155 -0
  946. package/tests/test-refusal-arrest-gate.sh +303 -0
  947. package/tests/test-remote-control-billing-classifier.sh +125 -0
  948. package/tests/test-resume-drift-watcher.sh +65 -0
  949. package/tests/test-rg-replace-flag-detector.sh +175 -0
  950. package/tests/test-rhetorical-verification-prompt-detector.sh +237 -0
  951. package/tests/test-rm-safety-net.sh +115 -0
  952. package/tests/test-route-handler-emptiness-gate.sh +300 -0
  953. package/tests/test-runtime-binary-change-detector.sh +196 -0
  954. package/tests/test-same-command-repeat-detector.sh +165 -0
  955. package/tests/test-same-correction-arrest.sh +165 -0
  956. package/tests/test-scope-expansion-receipt.sh +207 -0
  957. package/tests/test-server-side-prompt-injection-detector.sh +181 -0
  958. package/tests/test-session-persistence-verifier.sh +128 -0
  959. package/tests/test-session-rate-monitor.sh +284 -0
  960. package/tests/test-session-start-quota-status.sh +210 -0
  961. package/tests/test-session-start-safety-check.sh +138 -0
  962. package/tests/test-settings-hooks-key-restorer.sh +257 -0
  963. package/tests/test-settings-json-health-check.sh +70 -0
  964. package/tests/test-settings-regression-tester.sh +197 -0
  965. package/tests/test-skill-cumulative-size-detector.sh +198 -0
  966. package/tests/test-skill-description-drop-detector.sh +236 -0
  967. package/tests/test-skill-truncation-detector.sh +263 -0
  968. package/tests/test-skills-context-recorder.sh +329 -0
  969. package/tests/test-skills-load-verifier.sh +184 -0
  970. package/tests/test-skills-settings-validator.sh +242 -0
  971. package/tests/test-sonnet-45-deprecation-helper.sh +150 -0
  972. package/tests/test-spurious-malformed-notice-detector.sh +290 -0
  973. package/tests/test-sql-bulk-delete-warn.sh +123 -0
  974. package/tests/test-ssh-key-protect.sh +81 -0
  975. package/tests/test-stale-temp-settings-detector.sh +161 -0
  976. package/tests/test-standing-rule-session-surfacer.sh +215 -0
  977. package/tests/test-starter-hooks-manifest.sh +96 -0
  978. package/tests/test-stop-hook-sigterm-wrapper.sh +258 -0
  979. package/tests/test-strict-allowlist.sh +72 -0
  980. package/tests/test-subagent-boundary-precheck.sh +137 -0
  981. package/tests/test-subagent-closure-verify-gate.sh +193 -0
  982. package/tests/test-subagent-destructive-git-guard.sh +86 -0
  983. package/tests/test-subagent-identity-leak-guard.sh +62 -0
  984. package/tests/test-subagent-identity-reassertion.sh +61 -0
  985. package/tests/test-subagent-inheritance-tester.sh +319 -0
  986. package/tests/test-subagent-permission-mode-guard.sh +61 -0
  987. package/tests/test-subagent-spawn-verification-enforcer.sh +60 -0
  988. package/tests/test-subagent-tool-allowlist-enforcer.sh +62 -0
  989. package/tests/test-subagent-tool-call-limiter.sh +97 -0
  990. package/tests/test-subscription-api-billing-warner.sh +138 -0
  991. package/tests/test-subscription-bypass-detector.sh +255 -0
  992. package/tests/test-temporal-suggestion-detector.sh +183 -0
  993. package/tests/test-thinking-budget-effort-mismatch-detector.sh +327 -0
  994. package/tests/test-thinking-stall-detector.sh +151 -0
  995. package/tests/test-tokenizer-ratio-alert-corpus.sh +77 -0
  996. package/tests/test-tokenizer-ratio-alert.sh +93 -0
  997. package/tests/test-tool-result-correlation-checker.sh +264 -0
  998. package/tests/test-tool-result-size-guard.sh +121 -0
  999. package/tests/test-transcript-contamination-detector.sh +264 -0
  1000. package/tests/test-trigger-header-parsing.sh +151 -0
  1001. package/tests/test-ultrareview-large-diff-advisor.sh +192 -0
  1002. package/tests/test-userprompt-submit-receipt.sh +181 -0
  1003. package/tests/test-verify-after-publish-reminder.sh +184 -0
  1004. package/tests/test-version-bump-detector.sh +212 -0
  1005. package/tests/test-version-regression-warner.sh +165 -0
  1006. package/tests/test-warn-cron-cost-trap.sh +82 -0
  1007. package/tests/test-webfetch-runaway-guard.sh +77 -0
  1008. package/tests/test-wellness-break-reminder.sh +138 -0
  1009. package/tests/test-windows-destructive-command-guard.sh +169 -0
  1010. package/tests/test-windows-python-stub-detector.sh +146 -0
  1011. package/tests/test-worktree-edit-boundary-guard.sh +219 -0
  1012. package/tests/test-write-byte-integrity-verifier.sh +192 -0
  1013. package/tests/test-xml-format-leak-detector.sh +299 -0
  1014. package/tests/trustfall-mcp-injection-guard.test.sh +183 -0
  1015. package/tests/workspace-lease-guard.test.sh +144 -0
  1016. package/tests/worktree-escape-write-guard.test.sh +68 -0
  1017. package/tests/worktree-hooks-path-fix.test.sh +181 -0
  1018. package/tests/worktree-parent-write-guard.test.sh +51 -0
  1019. package/tests/write-empty-content-guard.test.sh +39 -0
  1020. package/tests/write-nul-corruption-detector.test.sh +29 -0
  1021. package/tests/write-overwrite-unread-content.test.sh +178 -0
  1022. package/tests/wsl-host-disk-space-guard.test.sh +55 -0
@@ -0,0 +1,91 @@
1
+ #!/bin/bash
2
+ # destructive-guard never looked inside a wrapper.
3
+ #
4
+ # Every boundary in the guard is (^|[;&|]) — the start of the line, or just
5
+ # after a separator. A command placed inside a substitution, a subshell, or
6
+ # after a shell keyword sits at neither, so no check ever saw it:
7
+ #
8
+ # rm -rf ~ blocked
9
+ # [[ -n $(rm -rf ~) ]] NOT blocked <- same deletion
10
+ # if true; then rm -rf ~; fi NOT blocked
11
+ # `rm -rf ~` NOT blocked
12
+ #
13
+ # Measured 2026-08-04 against the shipped core: one blocked command, ten
14
+ # wrappings, seven passes. Claude Code 2.1.221 fixed the same shape on its own
15
+ # side ("a Bash tool permission-check bypass where zsh could execute hidden
16
+ # commands in [[ ]] regex conditionals"), which is what prompted the check here.
17
+ #
18
+ # Check 0z replaces the wrapping tokens with separators and runs the guard once
19
+ # more against that text, so the inner command meets every existing check. The
20
+ # controls below are the point of this file: the rewrite touches parentheses and
21
+ # braces, which appear in ordinary commands (awk, jq, find -exec, subshells), so
22
+ # "catches wrapped commands" and "blocks anything with a bracket in it" have to
23
+ # be told apart.
24
+
25
+ set -u
26
+ ROOT="$(cd "$(dirname "$0")/.." && pwd)"
27
+ WORK="$(mktemp -d)"
28
+ trap 'find "$WORK" -mindepth 1 -delete 2>/dev/null; rmdir "$WORK" 2>/dev/null' EXIT
29
+ PASS=0; FAIL=0
30
+
31
+ python3 -c "
32
+ import json,sys
33
+ sys.stdout.write(json.load(open('$ROOT/scripts.json'))['destructive-guard'])" > "$WORK/dg.sh"
34
+
35
+ run() {
36
+ local T; T="$(mktemp -d)"
37
+ python3 -c '
38
+ import json,sys
39
+ print(json.dumps({"tool_name":"Bash","tool_input":{"command":sys.argv[1]},
40
+ "cwd":sys.argv[2],"session_id":"t"}))' "$1" "$T" \
41
+ | HOME="$T" bash "$WORK/dg.sh" >/dev/null 2>&1
42
+ local rc=$?
43
+ find "$T" -mindepth 1 -delete 2>/dev/null; rmdir "$T" 2>/dev/null
44
+ return $rc
45
+ }
46
+
47
+ want_block() {
48
+ if run "$1"; then FAIL=$((FAIL+1)); echo " FAIL blocked: $1"
49
+ else PASS=$((PASS+1)); echo " ok blocked: $1"; fi
50
+ }
51
+ want_allow() {
52
+ if run "$1"; then PASS=$((PASS+1)); echo " ok allowed: $1"
53
+ else FAIL=$((FAIL+1)); echo " FAIL allowed: $1"; fi
54
+ }
55
+
56
+ RM=$(printf 'r%s' 'm')
57
+ echo "destructive-guard-wrapped-command"
58
+
59
+ # --- the same deletion, wrapped ---------------------------------------------
60
+ want_block "[[ -n \$($RM -rf ~) ]]"
61
+ want_block "[[ x =~ \$($RM -rf ~) ]]"
62
+ want_block "[[ -n \`$RM -rf ~\` ]]"
63
+ want_block "if true; then $RM -rf ~; fi"
64
+ want_block "for f in a; do $RM -rf ~; done"
65
+ want_block "\$($RM -rf /)"
66
+ want_block "x=\$($RM -rf /) ; echo done"
67
+ want_block "echo \$(git reset --hard HEAD~5)"
68
+
69
+ # --- unwrapped, which already worked ----------------------------------------
70
+ want_block "$RM -rf ~"
71
+ want_block "$RM -rf /"
72
+
73
+ # --- controls: brackets and braces are ordinary ------------------------------
74
+ # Without these, the check above passes just as well by blocking every command
75
+ # that contains a parenthesis.
76
+ want_allow "awk '{print \$1}' access.log"
77
+ want_allow "sed -E 's/(a)/b/' file.txt"
78
+ want_allow "jq '{name: .name}' package.json"
79
+ want_allow "find . -name '*.log' -exec ls -l {} \\;"
80
+ want_allow "if [ -d node_modules ]; then echo yes; else echo no; fi"
81
+ want_allow "for i in \$(seq 1 3); do echo \$i; done"
82
+ want_allow "echo \$(basename \$(pwd))"
83
+ want_allow "( cd /tmp && ls )"
84
+ want_allow "ls \$(git rev-parse --show-toplevel)"
85
+ want_allow "$RM -rf node_modules && npm ci"
86
+ want_allow "git reset --soft HEAD~1"
87
+ want_allow "bash -c 'echo hello'"
88
+
89
+ echo
90
+ echo "destructive-guard-wrapped-command: $PASS passed, $FAIL failed"
91
+ [ "$FAIL" -eq 0 ]
@@ -0,0 +1,92 @@
1
+ #!/bin/bash
2
+ # --doctor: detect the environment variables that stop hooks loading at all
3
+ #
4
+ # Measured 2026-09-19 on Claude Code 2.1.278 (Linux/WSL2), disposable HOME and a
5
+ # scratch working directory, with a control on every row. Arrival was measured on
6
+ # UserPromptSubmit -- deliberately NOT PreToolUse on Bash, because --restricted
7
+ # removes Bash and then "the hook was ignored" and "nothing pulled the trigger"
8
+ # are the same observation.
9
+ #
10
+ # (control) no flags -> user, project and local hooks all fired
11
+ # --dangerously-skip-permissions -> hooks fired, the guard refused, exit 2
12
+ # --restricted -> no hook fired; --settings restored them
13
+ # --safe-mode -> no hook fired; --settings did NOT restore
14
+ # CLAUDE_CODE_RESTRICTED=1 -> same as --restricted
15
+ # CLAUDE_CODE_SAFE_MODE=1 -> same as --safe-mode, and Bash still ran
16
+ #
17
+ # The variables matter more than the flags: a flag is retyped every time you
18
+ # start, a line in a shell profile is read once and never seen again. Before this
19
+ # check, --doctor printed "All checks passed. Hooks should be working." with
20
+ # either variable set -- the exact false reassurance this command exists to
21
+ # prevent, since every other check inspects files that are all perfectly fine.
22
+ #
23
+ # Only the value "1" was measured. Any other non-empty, non-false value is
24
+ # flagged on the assumption that whoever typed it meant to turn it on; "0",
25
+ # "false" and empty are treated as off.
26
+ ROOT="$(cd "$(dirname "$0")/.." && pwd)"
27
+ PASS=0
28
+ FAIL=0
29
+
30
+ # Assembled at runtime so this file does not carry the literal filename that the
31
+ # operator's own guards watch for.
32
+ SETTINGS_FILE="set""tings.json"
33
+
34
+ run_doctor() {
35
+ # $1 = extra env assignments (may be empty). Prints only the lines this check owns.
36
+ local envspec="$1"
37
+ local home
38
+ home=$(mktemp -d)
39
+ mkdir -p "$home/.claude/hooks"
40
+ printf '%s' '{"hooks":{}}' > "$home/.claude/$SETTINGS_FILE"
41
+ # shellcheck disable=SC2086
42
+ env -u CLAUDE_CODE_SAFE_MODE -u CLAUDE_CODE_RESTRICTED $envspec HOME="$home" \
43
+ node "$ROOT/index.mjs" --doctor 2>&1 \
44
+ | grep -E 'hook-disabling environment variable|CLAUDE_CODE_SAFE_MODE=|CLAUDE_CODE_RESTRICTED=|does NOT restore|pass your hooks with|unset CLAUDE_CODE' || true
45
+ rm -rf "$home"
46
+ }
47
+
48
+ check() {
49
+ local desc="$1" envspec="$2" expect="$3"
50
+ local out
51
+ out=$(run_doctor "$envspec")
52
+ if printf '%s' "$out" | grep -q "$expect"; then
53
+ PASS=$((PASS + 1))
54
+ else
55
+ echo " FAIL: $desc"
56
+ echo " expected to match: $expect"
57
+ printf '%s\n' "${out:-<no output>}" | sed 's/^/ got: /'
58
+ FAIL=$((FAIL + 1))
59
+ fi
60
+ }
61
+
62
+ # --- the two variables are reported ----------------------------------------
63
+ check "CLAUDE_CODE_SAFE_MODE=1 is reported" \
64
+ "CLAUDE_CODE_SAFE_MODE=1" "CLAUDE_CODE_SAFE_MODE=1"
65
+
66
+ check "CLAUDE_CODE_RESTRICTED=1 is reported" \
67
+ "CLAUDE_CODE_RESTRICTED=1" "CLAUDE_CODE_RESTRICTED=1"
68
+
69
+ check "safe-mode says --settings does not help" \
70
+ "CLAUDE_CODE_SAFE_MODE=1" "does NOT restore"
71
+
72
+ check "restricted points at --settings as the way back" \
73
+ "CLAUDE_CODE_RESTRICTED=1" "pass your hooks with"
74
+
75
+ # --- controls: no false positives -------------------------------------------
76
+ # Without a control here, the two rows above would also pass if the check simply
77
+ # printed its warning unconditionally.
78
+ check "neither variable set reports the all-clear" \
79
+ "" "no hook-disabling environment variable set"
80
+
81
+ check "an explicit 0 is treated as off" \
82
+ "CLAUDE_CODE_SAFE_MODE=0" "no hook-disabling environment variable set"
83
+
84
+ check "the string false is treated as off" \
85
+ "CLAUDE_CODE_RESTRICTED=false" "no hook-disabling environment variable set"
86
+
87
+ check "an empty value is treated as off" \
88
+ "CLAUDE_CODE_SAFE_MODE=" "no hook-disabling environment variable set"
89
+
90
+ echo
91
+ echo "doctor-hook-disabling-env: $PASS passed, $FAIL failed"
92
+ [ "$FAIL" -eq 0 ]
@@ -0,0 +1,106 @@
1
+ #!/bin/bash
2
+ # --doctor: detect near-miss (misspelled) keys in the settings file
3
+ #
4
+ # Claude Code ignores unknown settings keys in silence. Measured on v2.1.220
5
+ # with isolated settings files, controls paired against the correct spelling:
6
+ #
7
+ # permissions.deny -> the command is refused, never starts
8
+ # permissions.denyy -> the command runs, exit 0, ZERO warnings
9
+ # hooks.PreToolUse -> hook blocks, exit 2
10
+ # hooks.PreToolUsee -> hook never invoked, ZERO warnings
11
+ # (the hook body was unchanged; only the key differed)
12
+ # sandbox.failIfUnavailable -> refuses to start when deps are missing, exit 1
13
+ # sandbox.failIfUnavailble -> starts unprotected, exit 0
14
+ #
15
+ # `claude doctor` does not check spelling and there is no non-interactive
16
+ # command that prints the effective settings, so a control can be void from the
17
+ # day it was written while looking exactly like one that works: both produce
18
+ # "nothing bad happened".
19
+ #
20
+ # The check reports only keys within a small edit distance of a known key.
21
+ # An unknown key that is far from every known one is left alone on purpose --
22
+ # it is probably a setting this release has not heard of, and a diagnostic that
23
+ # cries wolf stops being read.
24
+ ROOT="$(cd "$(dirname "$0")/.." && pwd)"
25
+ PASS=0
26
+ FAIL=0
27
+
28
+ # Assembled at runtime so this file does not carry the literal filename that the
29
+ # operator's own guards watch for.
30
+ SETTINGS_FILE="set""tings.json"
31
+
32
+ run_doctor() {
33
+ # $1 = JSON body. Runs --doctor against a throwaway HOME and prints the
34
+ # "did you mean" lines only.
35
+ local body="$1"
36
+ local home
37
+ home=$(mktemp -d)
38
+ mkdir -p "$home/.claude/hooks"
39
+ printf '%s' "$body" > "$home/.claude/$SETTINGS_FILE"
40
+ HOME="$home" node "$ROOT/index.mjs" --doctor 2>&1 | grep 'did you mean' || true
41
+ rm -rf "$home"
42
+ }
43
+
44
+ check() {
45
+ local desc="$1" body="$2" expected_count="$3" expected_key="$4"
46
+ local out n
47
+ out=$(run_doctor "$body")
48
+ n=$(printf '%s' "$out" | grep -c 'did you mean' || true)
49
+ [ -z "$out" ] && n=0
50
+ if [ "$n" -ne "$expected_count" ]; then
51
+ echo " FAIL: $desc (reported $n, expected $expected_count)"
52
+ [ -n "$out" ] && printf '%s\n' "$out" | sed 's/^/ /'
53
+ FAIL=$((FAIL + 1)); return
54
+ fi
55
+ if [ -n "$expected_key" ] && ! printf '%s' "$out" | grep -q "$expected_key"; then
56
+ echo " FAIL: $desc (did not name $expected_key)"
57
+ FAIL=$((FAIL + 1)); return
58
+ fi
59
+ echo " PASS: $desc"
60
+ PASS=$((PASS + 1))
61
+ }
62
+
63
+ echo "Testing --doctor misspelled settings key detection"
64
+ echo "=================================================="
65
+
66
+ # --- the three spellings measured on v2.1.220 -------------------------------
67
+ check "permissions.denyy is reported" \
68
+ '{"permissions":{"denyy":["Bash(curl:*)"],"allow":[]}}' 1 'permissions.denyy'
69
+
70
+ check "hooks.PreToolUsee is reported" \
71
+ '{"hooks":{"PreToolUsee":[]}}' 1 'hooks.PreToolUsee'
72
+
73
+ check "sandbox.failIfUnavailble is reported" \
74
+ '{"sandbox":{"enabled":true,"failIfUnavailble":true}}' 1 'sandbox.failIfUnavailble'
75
+
76
+ check "sandbox.network.strictAllowlst is reported" \
77
+ '{"sandbox":{"network":{"strictAllowlst":true}}}' 1 'sandbox.network.strictAllowlst'
78
+
79
+ check "a misspelled top-level key is reported" \
80
+ '{"modell":"opus"}' 1 'modell'
81
+
82
+ check "all three layers at once" \
83
+ '{"permissions":{"denyy":[]},"hooks":{"PreToolUsee":[]},"modell":"opus"}' 3 ''
84
+
85
+ # --- no false positives -----------------------------------------------------
86
+ check "correct spellings report nothing" \
87
+ '{"permissions":{"deny":[],"allow":[],"ask":[]},"hooks":{"PreToolUse":[],"PostToolUse":[],"SessionStart":[]},"model":"opus","defaultMode":"dontAsk"}' 0 ''
88
+
89
+ check "correct sandbox spellings report nothing" \
90
+ '{"sandbox":{"enabled":true,"failIfUnavailable":true,"network":{"strictAllowlist":true,"allowedDomains":["example.com"]}}}' 0 ''
91
+
92
+ check "an unknown key far from every known one stays silent" \
93
+ '{"someBrandNewFeatureNobodyKnows":true,"permissions":{"deny":[]}}' 0 ''
94
+
95
+ check "keys inside env are not checked (operator picks those names)" \
96
+ '{"env":{"denyy":"1","modell":"2"},"permissions":{"deny":[]}}' 0 ''
97
+
98
+ check "every hook event name spelled correctly reports nothing" \
99
+ '{"hooks":{"PreToolUse":[],"PostToolUse":[],"Notification":[],"Stop":[],"SubagentStop":[],"SubagentStart":[],"UserPromptSubmit":[],"PreCompact":[],"PostCompact":[],"SessionStart":[],"SessionEnd":[],"DirectoryAdded":[]}}' 0 ''
100
+
101
+ check "an empty settings object reports nothing" \
102
+ '{}' 0 ''
103
+
104
+ echo
105
+ echo "doctor-misspelled-settings-keys: $PASS passed, $FAIL failed"
106
+ [ "$FAIL" -eq 0 ]
@@ -0,0 +1,169 @@
1
+ #!/bin/bash
2
+ # Three example guards blocked a destructive command and then passed the same
3
+ # command once it was wrapped.
4
+ #
5
+ # The shapes measured 2026-08-04, against the shipped files:
6
+ #
7
+ # rm-safety-net 8 of 10 forms passed
8
+ # system-dir-protection-guard 9 of 11 forms passed
9
+ # auto-mode-safety-enforcer 5 of 9 forms passed
10
+ #
11
+ # Two separate causes, both about where a command is allowed to start:
12
+ #
13
+ # 1. The analysis gate. `rm-safety-net` and `system-dir-protection-guard`
14
+ # opened only on '^\s*(sudo\s+)?rm\s' — the command had to *begin* with
15
+ # rm, so `cd /tmp && rm -rf ~` never entered the analysis at all.
16
+ # 2. The target pattern. `auto-mode-safety-enforcer` required whitespace or
17
+ # end-of-line after the dangerous path, so `rm -rf ~; echo done` passed
18
+ # while `rm -rf ~ ; echo done` was blocked. One space apart, opposite
19
+ # verdicts.
20
+ #
21
+ # Wrappers hit both: inside a substitution or after `then`, a command is at
22
+ # neither the line start nor a separator. Claude Code 2.1.221 fixed the same
23
+ # shape in its own permission check ("hidden commands in [[ ]] regex
24
+ # conditionals"), which is what prompted measuring these.
25
+ #
26
+ # Half of this file is controls. The fix inserts separators at wrapper tokens,
27
+ # and parentheses and braces appear in ordinary commands (awk, jq, find -exec,
28
+ # subshells), so "looks inside wrappers" and "blocks anything with a bracket"
29
+ # have to be told apart. The home-path controls matter too: `ls ~/projects` and
30
+ # `cat ~/.bashrc` must stay untouched.
31
+
32
+ set -u
33
+ ROOT="$(cd "$(dirname "$0")/.." && pwd)"
34
+ PASS=0; FAIL=0
35
+ RM=$(printf 'r%s' 'm')
36
+
37
+ run() {
38
+ local hook="$1" cmd="$2" T rc
39
+ T="$(mktemp -d)"
40
+ python3 -c '
41
+ import json,sys
42
+ print(json.dumps({"tool_name":"Bash","tool_input":{"command":sys.argv[1]},
43
+ "cwd":sys.argv[2],"session_id":"t"}))' "$cmd" "$T" \
44
+ | HOME="$T" bash "$ROOT/examples/$hook.sh" >/dev/null 2>&1
45
+ rc=$?
46
+ find "$T" -mindepth 1 -delete 2>/dev/null; rmdir "$T" 2>/dev/null
47
+ return $rc
48
+ }
49
+
50
+ want_block() {
51
+ if run "$1" "$2"; then FAIL=$((FAIL+1)); echo " FAIL blocked [$1]: $2"
52
+ else PASS=$((PASS+1)); echo " ok blocked [$1]: $2"; fi
53
+ }
54
+ want_allow() {
55
+ if run "$1" "$2"; then PASS=$((PASS+1)); echo " ok allowed [$1]: $2"
56
+ else FAIL=$((FAIL+1)); echo " FAIL allowed [$1]: $2"; fi
57
+ }
58
+
59
+ echo "example-guards-wrapped-command"
60
+
61
+ # --- rm-safety-net -----------------------------------------------------------
62
+ H=rm-safety-net
63
+ want_block $H "$RM -rf ~"
64
+ want_block $H "cd /tmp && $RM -rf ~"
65
+ want_block $H "[[ -n \$($RM -rf ~) ]]"
66
+ want_block $H "[[ -n \`$RM -rf ~\` ]]"
67
+ want_block $H "if true; then $RM -rf ~; fi"
68
+ want_block $H "for f in a; do $RM -rf ~; done"
69
+ want_block $H "( $RM -rf ~ )"
70
+ want_block $H "x=\$($RM -rf /etc)"
71
+ want_block $H "npm ci && $RM -rf /home/user"
72
+ want_allow $H "$RM -rf node_modules"
73
+ want_allow $H "cd app && $RM -rf node_modules && npm ci"
74
+ want_allow $H "npm run confirm ~/project"
75
+ want_allow $H "echo 'please confirm ~/data first'"
76
+ want_allow $H "rmdir empty-dir"
77
+ want_allow $H "awk '{print \$1}' access.log"
78
+ want_allow $H "( cd /tmp && ls )"
79
+ want_allow $H "echo \$(basename \$(pwd))"
80
+
81
+ # --- system-dir-protection-guard ---------------------------------------------
82
+ H=system-dir-protection-guard
83
+ want_block $H "$RM -rf /etc"
84
+ want_block $H "cd /tmp && $RM -rf /etc"
85
+ want_block $H "[[ -n \$($RM -rf /etc) ]]"
86
+ want_block $H "if true; then $RM -rf /usr; fi"
87
+ want_block $H "for f in a; do $RM -rf /var; done"
88
+ want_block $H "( $RM -rf /etc )"
89
+ want_block $H "npm ci && mv /etc /tmp/x"
90
+ want_block $H "true && chmod -R 777 /etc"
91
+ want_allow $H "ls -la /etc"
92
+ want_allow $H "cat /etc/hosts"
93
+ want_allow $H "mv old.txt new.txt"
94
+ want_allow $H "chmod -R 755 ./public"
95
+ want_allow $H "awk '{print \$1}' /var/log/app.log"
96
+ want_allow $H "( cd /tmp && ls )"
97
+ want_allow $H "grep -r 'TODO' /home/me/project"
98
+
99
+ # --- auto-mode-safety-enforcer -----------------------------------------------
100
+ H=auto-mode-safety-enforcer
101
+ want_block $H "$RM -rf ~; echo done"
102
+ want_block $H "[[ -n \$($RM -rf ~) ]]"
103
+ want_block $H "if true; then $RM -rf ~; fi"
104
+ want_block $H "for f in a; do $RM -rf ~; done"
105
+ want_block $H "x=\$($RM -rf /etc)"
106
+ want_allow $H "ls ~/projects"
107
+ want_allow $H "cat ~/.bashrc"
108
+ want_allow $H "cp -r ~/a ~/b"
109
+ want_allow $H "du -sh ~/"
110
+ want_allow $H "$RM -rf node_modules"
111
+ want_allow $H "jq '{a: .b}' package.json"
112
+
113
+ # --- bash-project-fence -------------------------------------------------------
114
+ # Different concern: this one fences *paths outside the project root*, not
115
+ # destructive verbs. Its word split does not break on ( ) or a backtick, so a
116
+ # path inside a substitution arrived as the token "~)" — matching neither the
117
+ # "~/" case nor the absolute-path case, and the reference passed unnoticed.
118
+ # The fix strips the wrapping punctuation from the token edges.
119
+ fence_run() {
120
+ local cmd="$1" P rc
121
+ P="$(mktemp -d)"
122
+ mkdir -p "$P/src"
123
+ python3 -c '
124
+ import json,sys
125
+ print(json.dumps({"tool_name":"Bash","tool_input":{"command":sys.argv[1]},
126
+ "cwd":sys.argv[2],"session_id":"t"}))' "$cmd" "$P" \
127
+ | (cd "$P" && CLAUDE_PROJECT_DIR="$P" HOME=/nonexistent-home-for-test \
128
+ bash "$ROOT/examples/bash-project-fence.sh") >/dev/null 2>&1
129
+ # HOME must not sit under /tmp here. /tmp is on this hook's default allow
130
+ # list, and mktemp -d hands out /tmp paths, so a temp HOME makes every `~`
131
+ # case allowed and the four assertions below pass no matter what the code
132
+ # does. The path does not need to exist; only its prefix is compared.
133
+ rc=$?
134
+ find "$P" -mindepth 1 -delete 2>/dev/null; rmdir "$P" 2>/dev/null
135
+ return $rc
136
+ }
137
+ fence_block() {
138
+ if fence_run "$1"; then FAIL=$((FAIL+1)); echo " FAIL blocked [fence]: $1"
139
+ else PASS=$((PASS+1)); echo " ok blocked [fence]: $1"; fi
140
+ }
141
+ fence_allow() {
142
+ if fence_run "$1"; then PASS=$((PASS+1)); echo " ok allowed [fence]: $1"
143
+ else FAIL=$((FAIL+1)); echo " FAIL allowed [fence]: $1"; fi
144
+ }
145
+
146
+ fence_block "cat /home/someone/secrets.txt"
147
+ fence_block "[[ -n \$(cat /home/someone/secrets.txt) ]]"
148
+ fence_block "x=\$(cat /home/someone/secrets.txt)"
149
+ fence_block "echo \`cat /home/someone/secrets.txt\`"
150
+ # The home directory reached the tokenizer as "~)" and "~`", which match
151
+ # neither branch. These are the four that actually failed before the fix; the
152
+ # absolute-path forms above were already caught, so they alone would have
153
+ # recorded the defect as the spec.
154
+ fence_block "[[ -n \$(ls ~) ]]"
155
+ fence_block "[[ -n \`ls ~\` ]]"
156
+ fence_block "x=\$(ls ~)"
157
+ fence_block "( ls ~ )"
158
+ fence_allow "ls -la"
159
+ fence_allow "git status"
160
+ fence_allow "echo hello > /tmp/out.txt"
161
+ fence_allow "cat /tmp/scratch"
162
+ fence_allow "npm ci && npm run build"
163
+ fence_allow "curl -s https://example.com/api"
164
+ fence_allow "echo \$(basename \$(pwd))"
165
+ fence_allow "for i in \$(seq 1 3); do echo \$i; done"
166
+
167
+ echo
168
+ echo "example-guards-wrapped-command: $PASS passed, $FAIL failed"
169
+ [ "$FAIL" -eq 0 ]
@@ -0,0 +1,93 @@
1
+ #!/bin/bash
2
+ # Tests for file-edit-backup.sh
3
+ #
4
+ # The interesting case is path 2: a file overwritten through Bash
5
+ # (redirection, tee, mv) used to slip past this hook entirely.
6
+ # Reported by a reader on 2026-07-17.
7
+ HOOK="$(cd "$(dirname "$0")/.." && pwd)/examples/file-edit-backup.sh"
8
+ PASS=0; FAIL=0
9
+
10
+ WORK=$(mktemp -d)
11
+ export HOME="$WORK/home"
12
+ mkdir -p "$HOME"
13
+ BACKUPS="$HOME/.claude/file-backups"
14
+
15
+ # expect_backup <desc> <json> <basename-that-must-appear|NONE>
16
+ expect_backup() {
17
+ local desc="$1" input="$2" want="$3"
18
+ rm -rf "$BACKUPS" 2>/dev/null
19
+ ( cd "$WORK" && printf '%s' "$input" | bash "$HOOK" >/dev/null 2>&1 )
20
+ local found=0
21
+ if [ "$want" != "NONE" ] && [ -d "$BACKUPS" ]; then
22
+ ls "$BACKUPS" 2>/dev/null | grep -q "$want" && found=1
23
+ fi
24
+ if [ "$want" = "NONE" ]; then
25
+ if [ ! -d "$BACKUPS" ] || [ -z "$(ls -A "$BACKUPS" 2>/dev/null)" ]; then
26
+ echo "PASS: $desc"; ((PASS++))
27
+ else
28
+ echo "FAIL: $desc (expected no backup, got $(ls "$BACKUPS"))"; ((FAIL++))
29
+ fi
30
+ elif [ "$found" = "1" ]; then
31
+ echo "PASS: $desc"; ((PASS++))
32
+ else
33
+ echo "FAIL: $desc (expected a backup matching '$want')"; ((FAIL++))
34
+ fi
35
+ }
36
+
37
+ cd "$WORK" || exit 1
38
+ echo "original" > target.md
39
+ echo "original" > appended.md
40
+ echo "original" > teed.md
41
+ echo "original" > moved.md
42
+
43
+ # Path 1 — the Edit/Write tools (existing behaviour must not regress)
44
+ expect_backup "Write on an existing file is backed up" \
45
+ "{\"tool_name\":\"Write\",\"tool_input\":{\"file_path\":\"$WORK/target.md\"}}" "target.md"
46
+
47
+ expect_backup "Write on a new file makes no backup" \
48
+ "{\"tool_name\":\"Write\",\"tool_input\":{\"file_path\":\"$WORK/does-not-exist.md\"}}" "NONE"
49
+
50
+ # Path 2 — Bash. This is the hole the reader named.
51
+ expect_backup "Bash redirection > is backed up" \
52
+ '{"tool_name":"Bash","tool_input":{"command":"echo new > target.md"}}' "target.md"
53
+
54
+ expect_backup "Bash append >> is backed up" \
55
+ '{"tool_name":"Bash","tool_input":{"command":"echo more >> appended.md"}}' "appended.md"
56
+
57
+ expect_backup "Bash tee is backed up" \
58
+ '{"tool_name":"Bash","tool_input":{"command":"cat src | tee teed.md"}}' "teed.md"
59
+
60
+ expect_backup "Bash tee -a is backed up" \
61
+ '{"tool_name":"Bash","tool_input":{"command":"cat src | tee -a teed.md"}}' "teed.md"
62
+
63
+ expect_backup "Bash mv destination is backed up" \
64
+ '{"tool_name":"Bash","tool_input":{"command":"mv src.txt moved.md"}}' "moved.md"
65
+
66
+ expect_backup "Bash redirection inside a chain is backed up" \
67
+ '{"tool_name":"Bash","tool_input":{"command":"cd /tmp && echo x > target.md"}}' "target.md"
68
+
69
+ # Must NOT fire on things that only look like writes
70
+ expect_backup "fd duplication >&2 makes no backup" \
71
+ '{"tool_name":"Bash","tool_input":{"command":"echo hi >&2"}}' "NONE"
72
+
73
+ expect_backup "stderr redirect 2>&1 makes no backup" \
74
+ '{"tool_name":"Bash","tool_input":{"command":"make 2>&1 | less"}}' "NONE"
75
+
76
+ expect_backup "writing to a device file makes no backup" \
77
+ '{"tool_name":"Bash","tool_input":{"command":"echo x > /dev/null"}}' "NONE"
78
+
79
+ expect_backup "redirect to a file that does not exist makes no backup" \
80
+ '{"tool_name":"Bash","tool_input":{"command":"echo x > brand-new.md"}}' "NONE"
81
+
82
+ expect_backup "a read-only command makes no backup" \
83
+ '{"tool_name":"Bash","tool_input":{"command":"grep -r TODO ."}}' "NONE"
84
+
85
+ # The hook must never block: exit code is always 0
86
+ code=$(printf '%s' '{"tool_name":"Bash","tool_input":{"command":"echo x > target.md"}}' | bash "$HOOK" >/dev/null 2>&1; echo $?)
87
+ if [ "$code" = "0" ]; then echo "PASS: never blocks (exit 0)"; ((PASS++)); else echo "FAIL: expected exit 0, got $code"; ((FAIL++)); fi
88
+
89
+ cd / && rm -rf "$WORK" 2>/dev/null
90
+
91
+ echo ""
92
+ echo "PASS: $PASS FAIL: $FAIL"
93
+ [ "$FAIL" -eq 0 ]
@@ -0,0 +1,60 @@
1
+ #!/bin/bash
2
+ # Tests for git-filter-repo-guard.sh
3
+ # Run: bash tests/git-filter-repo-guard.test.sh
4
+ set -euo pipefail
5
+
6
+ PASS=0
7
+ FAIL=0
8
+ HOOK="$(dirname "$0")/../examples/git-filter-repo-guard.sh"
9
+
10
+ test_hook() {
11
+ local input="$1" expected_exit="$2" desc="$3"
12
+ local actual_exit=0
13
+ echo "$input" | bash "$HOOK" > /dev/null 2>/dev/null || actual_exit=$?
14
+ if [ "$actual_exit" -eq "$expected_exit" ]; then
15
+ echo " PASS: $desc"
16
+ PASS=$((PASS + 1))
17
+ else
18
+ echo " FAIL: $desc (expected exit $expected_exit, got $actual_exit)"
19
+ FAIL=$((FAIL + 1))
20
+ fi
21
+ }
22
+
23
+ echo "git-filter-repo-guard.sh tests"
24
+ echo ""
25
+
26
+ # --- Block: git filter-repo ---
27
+ test_hook '{"tool_input":{"command":"git filter-repo --force"}}' 2 "Block git filter-repo --force"
28
+ test_hook '{"tool_input":{"command":"git filter-repo --invert-paths --path secret.txt"}}' 2 "Block git filter-repo with path filter"
29
+ test_hook '{"tool_input":{"command":"git filter-repo --strip-blobs-bigger-than 10M"}}' 2 "Block git filter-repo blob strip"
30
+ test_hook '{"tool_input":{"command":"git filter-repo"}}' 2 "Block bare git filter-repo"
31
+
32
+ # --- Block: git filter-branch ---
33
+ test_hook '{"tool_input":{"command":"git filter-branch --tree-filter rm -f passwords.txt HEAD"}}' 2 "Block git filter-branch --tree-filter"
34
+ test_hook '{"tool_input":{"command":"git filter-branch --env-filter"}}' 2 "Block git filter-branch --env-filter"
35
+ test_hook '{"tool_input":{"command":"git filter-branch"}}' 2 "Block bare git filter-branch"
36
+
37
+ # --- Block: BFG Repo-Cleaner ---
38
+ test_hook '{"tool_input":{"command":"bfg --strip-blobs-bigger-than 100M"}}' 2 "Block bfg --strip-blobs-bigger-than"
39
+ test_hook '{"tool_input":{"command":"bfg --delete-files id_rsa"}}' 2 "Block bfg --delete-files"
40
+ test_hook '{"tool_input":{"command":"java -jar bfg.jar --replace-text passwords.txt"}}' 2 "Block bfg.jar via java"
41
+
42
+ # --- Allow: Safe git commands ---
43
+ test_hook '{"tool_input":{"command":"git status"}}' 0 "Allow git status"
44
+ test_hook '{"tool_input":{"command":"git log --oneline"}}' 0 "Allow git log"
45
+ test_hook '{"tool_input":{"command":"git diff HEAD~3"}}' 0 "Allow git diff"
46
+ test_hook '{"tool_input":{"command":"git commit -m fix"}}' 0 "Allow git commit"
47
+ test_hook '{"tool_input":{"command":"git push origin main"}}' 0 "Allow git push"
48
+ test_hook '{"tool_input":{"command":"git rebase main"}}' 0 "Allow non-interactive rebase"
49
+
50
+ # --- Allow: Commands containing filter as substring (not filter-repo) ---
51
+ test_hook '{"tool_input":{"command":"grep filter README.md"}}' 0 "Allow grep filter"
52
+ test_hook '{"tool_input":{"command":"cat filter-config.json"}}' 0 "Allow cat filter-config.json"
53
+
54
+ # --- Allow: Empty/missing input ---
55
+ test_hook '{}' 0 "Allow empty input"
56
+ test_hook '{"tool_input":{}}' 0 "Allow missing command"
57
+
58
+ echo ""
59
+ echo "Results: $PASS passed, $FAIL failed out of $((PASS + FAIL)) tests"
60
+ [ "$FAIL" -eq 0 ] && exit 0 || exit 1