cc-safe-setup 29.8.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 (1017) 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-dispatch-watchdog.sh +149 -0
  178. package/examples/completion-claim-without-verification-detector.sh +207 -0
  179. package/examples/composer-guard.sh +12 -0
  180. package/examples/compound-bash-permission-resolver.sh +156 -0
  181. package/examples/compound-command-allow.sh +1 -1
  182. package/examples/compound-command-deny-enforcer.sh +183 -0
  183. package/examples/compound-inject-guard.sh +12 -0
  184. package/examples/concurrent-edit-lock.sh +12 -0
  185. package/examples/conflict-marker-guard.sh +12 -0
  186. package/examples/consecutive-error-breaker.sh +0 -0
  187. package/examples/console-log-count.sh +1 -0
  188. package/examples/context-compact-advisor.sh +29 -2
  189. package/examples/context-length-budget.sh +69 -0
  190. package/examples/context-threshold-alert.sh +12 -0
  191. package/examples/context-usage-drift-alert.sh +41 -13
  192. package/examples/conversation-history-guard.sh +12 -0
  193. package/examples/core-file-protect-guard.sh +12 -0
  194. package/examples/cors-star-warn.sh +0 -0
  195. package/examples/cost-incident-self-audit.sh +162 -0
  196. package/examples/cowork-claude-md-load-checker.sh +100 -0
  197. package/examples/cowork-fuse-staleness-watcher.sh +140 -0
  198. package/examples/cowork-hook-absence-warner.sh +167 -0
  199. package/examples/cowork-model-picker-advisor.sh +115 -0
  200. package/examples/credential-exfil-guard.sh +65 -4
  201. package/examples/credential-file-cat-guard.sh +17 -1
  202. package/examples/cron-create-receipt.sh +112 -0
  203. package/examples/cron-modification-guard.sh +12 -0
  204. package/examples/cross-product-mcp-spawn-detector.sh +178 -0
  205. package/examples/cwd-project-boundary-guard.sh +0 -0
  206. package/examples/daemon-zombie-worker-surfacer.sh +118 -0
  207. package/examples/daily-cost-guard.sh +164 -0
  208. package/examples/daily-usage-tracker.sh +0 -0
  209. package/examples/dangerous-pip-flag-guard.sh +12 -0
  210. package/examples/db-connect-guard.sh +13 -1
  211. package/examples/denied-action-retry-guard.sh +12 -0
  212. package/examples/deny-bypass-detector.sh +12 -0
  213. package/examples/deny-rule-integrity-verifier.sh +181 -0
  214. package/examples/dependency-install-guard.sh +12 -0
  215. package/examples/deploy-guard.sh +14 -2
  216. package/examples/deploy-path-verify-guard.sh +12 -0
  217. package/examples/deployment-readback-gate.sh +135 -0
  218. package/examples/deployment-readback-gh-adapter.sh +247 -0
  219. package/examples/deployment-verify-guard.sh +25 -2
  220. package/examples/destructive-db-script-write-guard.sh +166 -0
  221. package/examples/destructive-migration-write-guard.sh +163 -0
  222. package/examples/diff-size-guard.sh +12 -0
  223. package/examples/disabled-feature-toggle-advisor.sh +88 -0
  224. package/examples/disk-partition-guard.sh +12 -0
  225. package/examples/dispatch-allowlist-preflight.sh +301 -0
  226. package/examples/dispatch-liveness-watchdog.sh +216 -0
  227. package/examples/dispatch-receipt.sh +174 -0
  228. package/examples/django-migrate-guard.sh +12 -0
  229. package/examples/dns-config-guard.sh +12 -0
  230. package/examples/docker-dangerous-guard.sh +12 -0
  231. package/examples/docker-volume-guard.sh +0 -0
  232. package/examples/dockerfile-latest-guard.sh +1 -0
  233. package/examples/dotenv-anthropic-key-billing-guard.sh +99 -0
  234. package/examples/dotenv-commit-guard.sh +12 -0
  235. package/examples/dotenv-read-guard.sh +12 -0
  236. package/examples/dotfile-protection-guard.sh +12 -0
  237. package/examples/dotnet-build-on-edit.sh +1 -1
  238. package/examples/drizzle-migrate-guard.sh +27 -2
  239. package/examples/echo-probe-spam-detector.sh +176 -0
  240. package/examples/edit-counter-test-gate.sh +12 -0
  241. package/examples/edit-error-counter.sh +1 -1
  242. package/examples/edit-guard.sh +12 -0
  243. package/examples/edit-old-string-validator.sh +12 -0
  244. package/examples/edit-quote-ambiguity-guard.sh +97 -0
  245. package/examples/edit-retry-loop-guard.sh +0 -0
  246. package/examples/edit-verify.sh +0 -0
  247. package/examples/env-inline-secret-guard.sh +14 -2
  248. package/examples/env-naming-convention.sh +0 -0
  249. package/examples/env-prod-guard.sh +0 -0
  250. package/examples/env-required-check.sh +0 -0
  251. package/examples/env-source-guard.sh +12 -0
  252. package/examples/env-var-check.sh +24 -1
  253. package/examples/ephemeral-container-detector.sh +147 -0
  254. package/examples/error-memory-guard.sh +12 -0
  255. package/examples/evidence-claim-gate.sh +187 -0
  256. package/examples/exploration-budget-guard.sh +12 -0
  257. package/examples/expo-eject-guard.sh +13 -0
  258. package/examples/extended-thinking-loop-guard.sh +139 -0
  259. package/examples/extended-thinking-resume-warning.sh +119 -0
  260. package/examples/extended-thinking-tool-use-mismatch-detector.sh +212 -0
  261. package/examples/fabricated-command-detector.sh +145 -0
  262. package/examples/false-disk-full-guard.sh +63 -0
  263. package/examples/feature-deprecation-detector.sh +109 -0
  264. package/examples/file-change-tracker.sh +1 -1
  265. package/examples/file-change-undo-tracker.sh +0 -0
  266. package/examples/file-edit-backup.sh +63 -14
  267. package/examples/file-reference-check.sh +0 -0
  268. package/examples/file-size-limit.sh +12 -0
  269. package/examples/financial-operation-guard.sh +12 -0
  270. package/examples/firewall-guard.sh +12 -0
  271. package/examples/fish-shell-wrapper.sh +125 -7
  272. package/examples/five-hundred-milestone.sh +1 -0
  273. package/examples/flask-static-route-guard.sh +89 -0
  274. package/examples/forbidden-response-phrase-detector.sh +161 -0
  275. package/examples/gem-push-guard.sh +13 -0
  276. package/examples/gh-cli-destructive-guard.sh +13 -1
  277. package/examples/git-checkout-safety-guard.sh +12 -0
  278. package/examples/git-checkout-uncommitted-guard.sh +12 -0
  279. package/examples/git-config-guard.sh +12 -0
  280. package/examples/git-crypt-worktree-guard.sh +12 -0
  281. package/examples/git-filter-repo-guard.sh +56 -0
  282. package/examples/git-history-rewrite-guard.sh +12 -0
  283. package/examples/git-hook-bypass-guard.sh +0 -0
  284. package/examples/git-maintenance-guard.sh +83 -0
  285. package/examples/git-merge-conflict-prevent.sh +0 -0
  286. package/examples/git-message-length-check.sh +0 -0
  287. package/examples/git-message-length.sh +0 -0
  288. package/examples/git-operations-require-approval.sh +68 -14
  289. package/examples/git-pack-temp-cleanup-guard.sh +102 -0
  290. package/examples/git-push-blast-radius-guard.sh +218 -0
  291. package/examples/git-remote-guard.sh +24 -3
  292. package/examples/git-rm-orphan-wipe-guard.sh +85 -0
  293. package/examples/git-stash-before-checkout.sh +12 -0
  294. package/examples/git-stash-before-danger.sh +0 -0
  295. package/examples/git-submodule-guard.sh +69 -2
  296. package/examples/git-tag-guard.sh +12 -0
  297. package/examples/github-actions-secret-guard.sh +0 -0
  298. package/examples/gitignore-check.sh +0 -0
  299. package/examples/gitops-drift-guard.sh +12 -0
  300. package/examples/go-mod-tidy-warn.sh +1 -0
  301. package/examples/go-vet-after-edit.sh +12 -0
  302. package/examples/goal-iteration-limit-warner.sh +152 -0
  303. package/examples/grep-nul-false-negative-guard.sh +30 -0
  304. package/examples/growthbook-flag-monitor.sh +257 -0
  305. package/examples/hallucination-url-check.sh +1 -1
  306. package/examples/halt-signal-detector.sh +135 -0
  307. package/examples/handoff-on-clear.sh +65 -0
  308. package/examples/hardcoded-ip-guard.sh +1 -0
  309. package/examples/headless-empty-result-guard.sh +0 -0
  310. package/examples/headless-stop-guard.sh +0 -0
  311. package/examples/helm-install-guard.sh +2 -1
  312. package/examples/home-critical-bash-guard.sh +17 -1
  313. package/examples/hook-debug-wrapper.sh +6 -2
  314. package/examples/hook-permission-fixer.sh +0 -0
  315. package/examples/hook-self-disable-detector.sh +99 -0
  316. package/examples/hook-stdout-sanitizer.sh +6 -2
  317. package/examples/hook-tamper-guard.sh +12 -0
  318. package/examples/idle-session-cost-alert.sh +0 -0
  319. package/examples/image-dimension-guard.sh +109 -0
  320. package/examples/image-file-validator.sh +0 -0
  321. package/examples/iteration-quality-degradation-detector.sh +170 -0
  322. package/examples/java-compile-on-edit.sh +1 -1
  323. package/examples/json-syntax-check.sh +0 -0
  324. package/examples/k8s-production-guard.sh +13 -1
  325. package/examples/kill-process-guard.sh +12 -0
  326. package/examples/kubernetes-guard.sh +13 -1
  327. package/examples/laravel-artisan-guard.sh +13 -0
  328. package/examples/large-file-guard.sh +1 -1
  329. package/examples/log-level-guard.sh +0 -0
  330. package/examples/log-truncation-guard.sh +12 -0
  331. package/examples/long-session-malformed-tool-call-detector.sh +183 -0
  332. package/examples/loop-detector.sh +12 -0
  333. package/examples/magic-number-warn.sh +1 -0
  334. package/examples/main-branch-warn.sh +12 -0
  335. package/examples/markdown-link-check.sh +0 -0
  336. package/examples/max-concurrent-agents.sh +12 -0
  337. package/examples/max-edit-size-guard.sh +13 -0
  338. package/examples/max-file-count-guard.sh +0 -0
  339. package/examples/max-file-delete-count.sh +0 -0
  340. package/examples/max-function-length.sh +1 -0
  341. package/examples/max-import-count.sh +0 -0
  342. package/examples/max-subagent-count.sh +0 -0
  343. package/examples/mcp-config-freeze.sh +12 -0
  344. package/examples/mcp-config-poisoning-audit.sh +150 -0
  345. package/examples/mcp-data-boundary.sh +1 -1
  346. package/examples/mcp-misdiagnosis-arrest.sh +209 -0
  347. package/examples/mcp-orphan-leak-warner.sh +49 -0
  348. package/examples/mcp-permissions-ask-warner.sh +151 -0
  349. package/examples/mcp-routine-approval-detector.sh +154 -0
  350. package/examples/mcp-server-allowlist.sh +12 -0
  351. package/examples/mcp-server-guard.sh +12 -0
  352. package/examples/mcp-startup-bloat-detector.sh +87 -0
  353. package/examples/mcp-stdio-compatibility-test.sh +153 -0
  354. package/examples/mcp-tool-audit-log.sh +0 -0
  355. package/examples/mcp-tool-guard.sh +101 -1
  356. package/examples/mcp-warmup-wait.sh +0 -0
  357. package/examples/memory-chain-audit.sh +56 -0
  358. package/examples/memory-orphan-detector.sh +188 -0
  359. package/examples/memory-write-guard.sh +99 -17
  360. package/examples/migration-verify-guard.sh +12 -0
  361. package/examples/model-swap-suggester.sh +177 -0
  362. package/examples/model-version-alert.sh +5 -1
  363. package/examples/model-version-lock.sh +63 -0
  364. package/examples/move-delete-sequence-guard.sh +33 -2
  365. package/examples/multi-file-plan-routing-gate.sh +192 -0
  366. package/examples/multi-vendor-concurrent-warner.sh +108 -0
  367. package/examples/multi-window-auth-drift-detector.sh +183 -0
  368. package/examples/multiline-command-approver.sh +161 -23
  369. package/examples/nested-background-agent-guard.sh +109 -0
  370. package/examples/nested-spawn-inflight-guard.sh +178 -0
  371. package/examples/network-exfil-guard.sh +12 -0
  372. package/examples/network-guard.sh +12 -0
  373. package/examples/network-interface-guard.sh +12 -0
  374. package/examples/nextjs-env-guard.sh +1 -1
  375. package/examples/no-absolute-import.sh +0 -0
  376. package/examples/no-alert-confirm-prompt.sh +0 -0
  377. package/examples/no-anonymous-default-export.sh +0 -0
  378. package/examples/no-any-type.sh +0 -0
  379. package/examples/no-any-typescript.sh +1 -0
  380. package/examples/no-ask-human.sh +12 -0
  381. package/examples/no-assignment-in-condition.sh +0 -0
  382. package/examples/no-base64-exfil.sh +12 -0
  383. package/examples/no-callback-hell.sh +0 -0
  384. package/examples/no-circular-dependency.sh +0 -0
  385. package/examples/no-cleartext-storage.sh +0 -0
  386. package/examples/no-commented-code.sh +0 -0
  387. package/examples/no-commit-fixup.sh +0 -0
  388. package/examples/no-console-assert.sh +0 -0
  389. package/examples/no-console-error-swallow.sh +0 -0
  390. package/examples/no-console-in-prod.sh +0 -0
  391. package/examples/no-console-log-commit.sh +12 -0
  392. package/examples/no-console-log.sh +0 -0
  393. package/examples/no-console-time.sh +0 -0
  394. package/examples/no-cors-wildcard.sh +4 -1
  395. package/examples/no-curl-upload.sh +0 -0
  396. package/examples/no-dangerouslySetInnerHTML.sh +0 -0
  397. package/examples/no-dangling-await.sh +1 -0
  398. package/examples/no-debug-commit.sh +12 -0
  399. package/examples/no-debug-in-commit.sh +0 -0
  400. package/examples/no-deep-nesting.sh +0 -0
  401. package/examples/no-deep-relative-import.sh +1 -0
  402. package/examples/no-default-credentials.sh +0 -0
  403. package/examples/no-deploy-friday.sh +13 -1
  404. package/examples/no-disabled-test.sh +0 -0
  405. package/examples/no-document-write.sh +0 -0
  406. package/examples/no-empty-function.sh +0 -0
  407. package/examples/no-eval-in-template.sh +0 -0
  408. package/examples/no-eval-template.sh +3 -1
  409. package/examples/no-eval.sh +0 -0
  410. package/examples/no-exec-user-input.sh +0 -0
  411. package/examples/no-fixme-ship.sh +12 -0
  412. package/examples/no-floating-promises.sh +0 -0
  413. package/examples/no-force-flag.sh +22 -5
  414. package/examples/no-force-install.sh +0 -0
  415. package/examples/no-git-amend.sh +12 -0
  416. package/examples/no-git-rebase-public.sh +0 -0
  417. package/examples/no-global-install.sh +12 -0
  418. package/examples/no-global-state.sh +0 -0
  419. package/examples/no-hardcoded-port.sh +1 -0
  420. package/examples/no-hardcoded-url.sh +0 -0
  421. package/examples/no-helmet-missing.sh +0 -0
  422. package/examples/no-http-url.sh +1 -0
  423. package/examples/no-http-without-https.sh +0 -0
  424. package/examples/no-inline-style.sh +0 -0
  425. package/examples/no-inline-styles.sh +1 -0
  426. package/examples/no-innerhtml.sh +0 -0
  427. package/examples/no-install-global.sh +12 -0
  428. package/examples/no-jwt-in-url.sh +0 -0
  429. package/examples/no-large-commit.sh +0 -0
  430. package/examples/no-localhost-expose.sh +0 -0
  431. package/examples/no-magic-number.sh +0 -0
  432. package/examples/no-md5-sha1.sh +0 -0
  433. package/examples/no-mixed-line-endings.sh +8 -1
  434. package/examples/no-mutation-in-reducer.sh +0 -0
  435. package/examples/no-nested-ternary.sh +0 -0
  436. package/examples/no-network-exfil.sh +0 -0
  437. package/examples/no-open-redirect.sh +0 -0
  438. package/examples/no-output-truncation.sh +12 -0
  439. package/examples/no-package-downgrade.sh +0 -0
  440. package/examples/no-package-lock-edit.sh +12 -0
  441. package/examples/no-path-join-user-input.sh +0 -0
  442. package/examples/no-port-bind.sh +0 -0
  443. package/examples/no-process-exit.sh +0 -0
  444. package/examples/no-prototype-pollution.sh +0 -0
  445. package/examples/no-push-without-ci.sh +0 -0
  446. package/examples/no-push-without-tests.sh +12 -0
  447. package/examples/no-raw-password-in-url.sh +0 -0
  448. package/examples/no-root-user-docker.sh +1 -0
  449. package/examples/no-root-write.sh +12 -0
  450. package/examples/no-secrets-in-args.sh +4 -1
  451. package/examples/no-secrets-in-logs.sh +0 -0
  452. package/examples/no-sensitive-log.sh +0 -0
  453. package/examples/no-sleep-in-hooks.sh +0 -0
  454. package/examples/no-star-import-python.sh +1 -0
  455. package/examples/no-string-concat-sql.sh +0 -0
  456. package/examples/no-sudo-guard.sh +12 -0
  457. package/examples/no-sync-fs.sh +0 -0
  458. package/examples/no-todo-in-merge.sh +0 -0
  459. package/examples/no-todo-in-production.sh +1 -0
  460. package/examples/no-todo-without-issue.sh +0 -0
  461. package/examples/no-unused-import.sh +0 -0
  462. package/examples/no-var-keyword.sh +0 -0
  463. package/examples/no-verify-blocker.sh +12 -0
  464. package/examples/no-wget-piped-bash.sh +12 -0
  465. package/examples/no-wildcard-cors.sh +0 -0
  466. package/examples/no-wildcard-delete.sh +0 -0
  467. package/examples/no-wildcard-import.sh +0 -0
  468. package/examples/no-with-statement.sh +0 -0
  469. package/examples/no-write-outside-src.sh +0 -0
  470. package/examples/no-xml-external-entity.sh +0 -0
  471. package/examples/non-english-quality-warner.sh +156 -0
  472. package/examples/notify-waiting.sh +1 -1
  473. package/examples/npm-audit-warn.sh +0 -0
  474. package/examples/npm-global-install-guard.sh +12 -0
  475. package/examples/npm-publish-guard.sh +12 -0
  476. package/examples/npm-script-injection.sh +0 -0
  477. package/examples/npm-supply-chain-guard.sh +0 -0
  478. package/examples/nuxt-config-guard.sh +1 -0
  479. package/examples/oauth-refresh-monitor.sh +210 -0
  480. package/examples/opus-degradation-tracker.sh +187 -0
  481. package/examples/opus48-routine-task-warning.sh +196 -0
  482. package/examples/opus48-thinking-wedge-advisor.sh +143 -0
  483. package/examples/output-credential-scan.sh +1 -1
  484. package/examples/output-secret-mask.sh +31 -9
  485. package/examples/output-token-spike-detector.sh +145 -0
  486. package/examples/package-json-guard.sh +12 -0
  487. package/examples/package-lock-frozen.sh +12 -0
  488. package/examples/parallel-batch-size-limiter.sh +121 -0
  489. package/examples/parallel-cascade-detector.sh +116 -0
  490. package/examples/partial-view-claim-arrest.sh +174 -0
  491. package/examples/path-deny-bash-guard.sh +12 -0
  492. package/examples/path-traversal-guard.sh +12 -0
  493. package/examples/per-prompt-token-cap.sh +124 -0
  494. package/examples/permission-audit-log.sh +1 -1
  495. package/examples/permission-denial-enforcer.sh +12 -0
  496. package/examples/permission-entry-validator.sh +0 -0
  497. package/examples/persisted-1m-model-advisor.sh +88 -0
  498. package/examples/php-lint-on-edit.sh +1 -1
  499. package/examples/pii-upload-guard.sh +12 -0
  500. package/examples/pip-publish-guard.sh +13 -0
  501. package/examples/pip-requirements-guard.sh +12 -0
  502. package/examples/pip-venv-required.sh +12 -0
  503. package/examples/plan-mode-edit-guard.sh +12 -0
  504. package/examples/plan-mode-enforcer.sh +12 -0
  505. package/examples/plan-mode-strict-guard.sh +12 -0
  506. package/examples/plugin-hooks-json-bloat-detector.sh +169 -0
  507. package/examples/plugin-process-cleanup.sh +0 -0
  508. package/examples/polyglot-rm-guard.sh +12 -0
  509. package/examples/post-compact-safety.sh +12 -0
  510. package/examples/post-edit-disk-verify.sh +152 -0
  511. package/examples/powershell-remove-item-guard.sh +85 -0
  512. package/examples/pr-description-check.sh +0 -0
  513. package/examples/pr-duplicate-guard.sh +13 -0
  514. package/examples/pre-bash-sed-line-ending-windows.sh +87 -0
  515. package/examples/pre-compact-knowledge-save.sh +0 -0
  516. package/examples/pre-compact-transcript-backup.sh +0 -0
  517. package/examples/pre-execution-claim-detector.sh +179 -0
  518. package/examples/prefer-builtin-tools.sh +10 -1
  519. package/examples/prefer-const.sh +0 -0
  520. package/examples/prefer-dedicated-tools.sh +12 -0
  521. package/examples/prefer-optional-chaining.sh +0 -0
  522. package/examples/prisma-migrate-guard.sh +24 -7
  523. package/examples/production-port-kill-guard.sh +12 -0
  524. package/examples/prompt-injection-guard.sh +2 -1
  525. package/examples/prompt-usage-logger.sh +0 -0
  526. package/examples/protect-claudemd.sh +12 -0
  527. package/examples/protect-dotfiles.sh +12 -0
  528. package/examples/proxy-capture-suggester.sh +159 -0
  529. package/examples/public-artefact-socratic-narrowing.sh +232 -0
  530. package/examples/public-repo-push-guard.sh +12 -0
  531. package/examples/push-requires-test-pass-record.sh +0 -0
  532. package/examples/push-requires-test-pass.sh +12 -0
  533. package/examples/quota-anomaly-detector.sh +173 -0
  534. package/examples/quota-reset-audit.sh +58 -0
  535. package/examples/quoted-flag-approver.sh +99 -10
  536. package/examples/rails-migration-guard.sh +12 -0
  537. package/examples/rate-limit-guard.sh +0 -0
  538. package/examples/read-all-files-enforcer.sh +0 -0
  539. package/examples/read-budget-guard.sh +12 -0
  540. package/examples/read-loop-detector.sh +59 -0
  541. package/examples/read-once-guard.sh +96 -0
  542. package/examples/read-only-mode.sh +12 -0
  543. package/examples/readme-exists-check.sh +0 -0
  544. package/examples/record-read-coverage.sh +73 -0
  545. package/examples/redirect-fragment-warner.sh +149 -0
  546. package/examples/redis-flushall-guard.sh +13 -0
  547. package/examples/redundant-read-blocker.sh +132 -0
  548. package/examples/refusal-arrest-gate.sh +248 -0
  549. package/examples/registry-publish-guard.sh +13 -1
  550. package/examples/remote-control-billing-classifier.sh +135 -0
  551. package/examples/replace-all-guard.sh +12 -0
  552. package/examples/repo-visibility-guard.sh +12 -0
  553. package/examples/reroute-after-block-guard.sh +150 -0
  554. package/examples/response-budget-guard.sh +0 -0
  555. package/examples/resume-drift-watcher.sh +57 -0
  556. package/examples/rg-replace-flag-detector.sh +125 -0
  557. package/examples/rhetorical-verification-prompt-detector.sh +102 -0
  558. package/examples/ripgrep-permission-fix.sh +0 -0
  559. package/examples/rm-safety-net.sh +151 -8
  560. package/examples/role-tool-guard.sh +12 -0
  561. package/examples/route-handler-emptiness-gate.sh +324 -0
  562. package/examples/ruby-lint-on-edit.sh +1 -1
  563. package/examples/runtime-binary-change-detector.sh +102 -0
  564. package/examples/same-command-repeat-detector.sh +196 -0
  565. package/examples/same-correction-arrest.sh +169 -0
  566. package/examples/sandbox-denywrite-enforcer.sh +78 -0
  567. package/examples/sandbox-relative-path-audit.sh +83 -25
  568. package/examples/sandbox-write-verify.sh +12 -0
  569. package/examples/schema-migration-guard.sh +0 -0
  570. package/examples/scope-expansion-receipt.sh +178 -0
  571. package/examples/scope-guard.sh +88 -9
  572. package/examples/secret-file-read-guard.sh +12 -0
  573. package/examples/secret-file-write-guard.sh +150 -0
  574. package/examples/self-modify-bypass-guard.sh +0 -0
  575. package/examples/sensitive-file-read-guard.sh +23 -3
  576. package/examples/sensitive-log-guard.sh +1 -0
  577. package/examples/server-side-prompt-injection-detector.sh +69 -0
  578. package/examples/session-agent-cost-limiter.sh +12 -0
  579. package/examples/session-backup-on-start.sh +1 -1
  580. package/examples/session-cost-alert.sh +12 -0
  581. package/examples/session-drift-guard.sh +12 -0
  582. package/examples/session-duration-guard.sh +25 -2
  583. package/examples/session-end-logger.sh +0 -0
  584. package/examples/session-health-monitor.sh +0 -0
  585. package/examples/session-index-repair.sh +1 -1
  586. package/examples/session-memory-watchdog.sh +1 -0
  587. package/examples/session-permission-reset-guard.sh +12 -0
  588. package/examples/session-persistence-verifier.sh +93 -0
  589. package/examples/session-plugin-pin-watch.sh +68 -0
  590. package/examples/session-rate-monitor.sh +176 -0
  591. package/examples/session-resume-env-fix.sh +0 -0
  592. package/examples/session-start-quota-status.sh +193 -0
  593. package/examples/session-start-safety-check.sh +55 -3
  594. package/examples/session-state-saver.sh +0 -0
  595. package/examples/session-summary-stop.sh +1 -1
  596. package/examples/session-summary.sh +0 -0
  597. package/examples/session-token-counter.sh +1 -1
  598. package/examples/settings-hooks-key-restorer.sh +99 -0
  599. package/examples/settings-json-health-check.sh +57 -0
  600. package/examples/settings-json-model-guard.sh +0 -0
  601. package/examples/settings-regression-tester.sh +188 -0
  602. package/examples/shell-config-truncation-guard.sh +12 -0
  603. package/examples/shell-wrapper-guard.sh +12 -0
  604. package/examples/skill-cumulative-size-detector.sh +104 -0
  605. package/examples/skill-description-drop-detector.sh +148 -0
  606. package/examples/skill-gate.sh +0 -0
  607. package/examples/skill-truncation-detector.sh +154 -0
  608. package/examples/skills-context-recorder.sh +167 -0
  609. package/examples/skills-load-verifier.sh +96 -0
  610. package/examples/skills-settings-validator.sh +139 -0
  611. package/examples/sonnet-45-deprecation-helper.sh +85 -0
  612. package/examples/spec-file-scope-guard.sh +12 -0
  613. package/examples/spring-profile-guard.sh +1 -0
  614. package/examples/spurious-malformed-notice-detector.sh +247 -0
  615. package/examples/sql-bulk-delete-warn.sh +88 -0
  616. package/examples/sql-injection-detect.sh +0 -0
  617. package/examples/ssh-key-protect.sh +12 -0
  618. package/examples/staged-secret-scan.sh +22 -1
  619. package/examples/stale-temp-settings-detector.sh +86 -0
  620. package/examples/standing-rule-session-surfacer.sh +137 -0
  621. package/examples/stop-hook-sigterm-wrapper.sh +182 -0
  622. package/examples/stop-transcript-write-health.sh +64 -0
  623. package/examples/strict-allowlist.sh +57 -15
  624. package/examples/strip-coauthored-by.sh +50 -10
  625. package/examples/subagent-blast-radius-guard.sh +184 -0
  626. package/examples/subagent-boundary-precheck.sh +126 -0
  627. package/examples/subagent-budget-guard.sh +12 -0
  628. package/examples/subagent-claudemd-inject.sh +0 -0
  629. package/examples/subagent-closure-verify-gate.sh +164 -0
  630. package/examples/subagent-destructive-git-guard.sh +120 -0
  631. package/examples/subagent-error-detector.sh +0 -0
  632. package/examples/subagent-forged-system-reminder-guard.sh +156 -0
  633. package/examples/subagent-identity-leak-guard.sh +102 -0
  634. package/examples/subagent-identity-reassertion.sh +51 -0
  635. package/examples/subagent-inheritance-tester.sh +179 -0
  636. package/examples/subagent-permission-mode-guard.sh +110 -0
  637. package/examples/subagent-scope-guard.sh +12 -0
  638. package/examples/subagent-spawn-verification-enforcer.sh +102 -0
  639. package/examples/subagent-tool-allowlist-enforcer.sh +101 -0
  640. package/examples/subagent-tool-call-limiter.sh +87 -15
  641. package/examples/subcommand-chain-guard.sh +12 -0
  642. package/examples/subscription-api-billing-warner.sh +160 -0
  643. package/examples/subscription-bypass-detector.sh +152 -0
  644. package/examples/svelte-lint-on-edit.sh +1 -0
  645. package/examples/swift-build-on-edit.sh +1 -1
  646. package/examples/symlink-guard.sh +27 -2
  647. package/examples/symlink-protect.sh +1 -0
  648. package/examples/system-dir-protection-guard.sh +73 -8
  649. package/examples/system-message-workaround.sh +38 -13
  650. package/examples/system-package-guard.sh +12 -0
  651. package/examples/systemd-service-guard.sh +12 -0
  652. package/examples/task-integrity-guard.sh +12 -0
  653. package/examples/temp-file-cleanup.sh +1 -1
  654. package/examples/temporal-suggestion-detector.sh +135 -0
  655. package/examples/terraform-guard.sh +27 -6
  656. package/examples/test-after-edit.sh +1 -1
  657. package/examples/test-before-push.sh +12 -0
  658. package/examples/test-coverage-reminder.sh +24 -1
  659. package/examples/thinking-budget-effort-mismatch-detector.sh +149 -0
  660. package/examples/timezone-guard.sh +0 -0
  661. package/examples/tmp-output-size-guard.sh +0 -0
  662. package/examples/todo-check.sh +1 -1
  663. package/examples/token-budget-guard.sh +12 -0
  664. package/examples/token-budget-per-task.sh +12 -0
  665. package/examples/token-usage-tracker.sh +7 -1
  666. package/examples/tokenizer-ratio-alert-corpus.sh +90 -0
  667. package/examples/tokenizer-ratio-alert.sh +104 -0
  668. package/examples/tool-call-rate-limiter.sh +0 -0
  669. package/examples/tool-result-correlation-checker.sh +167 -0
  670. package/examples/tool-result-size-guard.sh +132 -0
  671. package/examples/tool-retry-budget-guard.sh +12 -0
  672. package/examples/transcript-contamination-detector.sh +138 -0
  673. package/examples/trustfall-mcp-injection-guard.sh +103 -0
  674. package/examples/ultrareview-large-diff-advisor.sh +184 -0
  675. package/examples/unbounded-output-guard.sh +94 -0
  676. package/examples/uncommitted-changes-stop.sh +1 -0
  677. package/examples/uncommitted-discard-guard.sh +23 -5
  678. package/examples/uncommitted-work-guard.sh +12 -0
  679. package/examples/usage-warn.sh +0 -0
  680. package/examples/user-account-guard.sh +12 -0
  681. package/examples/userprompt-submit-receipt.sh +123 -0
  682. package/examples/variable-expansion-guard.sh +12 -0
  683. package/examples/verify-after-publish-reminder.sh +93 -0
  684. package/examples/verify-before-commit.sh +12 -0
  685. package/examples/version-bump-detector.sh +156 -0
  686. package/examples/version-regression-warner.sh +144 -0
  687. package/examples/vue-lint-on-edit.sh +1 -0
  688. package/examples/warn-cron-cost-trap.sh +173 -0
  689. package/examples/webfetch-runaway-guard.sh +89 -0
  690. package/examples/wellness-break-reminder.sh +118 -0
  691. package/examples/windows-destructive-command-guard.sh +177 -0
  692. package/examples/windows-path-guard.sh +12 -0
  693. package/examples/windows-python-stub-detector.sh +63 -0
  694. package/examples/work-hours-guard.sh +12 -0
  695. package/examples/working-directory-fence.sh +12 -0
  696. package/examples/workspace-lease-guard.sh +205 -0
  697. package/examples/worktree-create-log.sh +1 -0
  698. package/examples/worktree-delete-guard.sh +12 -0
  699. package/examples/worktree-edit-boundary-guard.sh +127 -0
  700. package/examples/worktree-escape-write-guard.sh +114 -0
  701. package/examples/worktree-hook-linker.sh +0 -0
  702. package/examples/worktree-hooks-path-fix.sh +111 -0
  703. package/examples/worktree-parent-write-guard.sh +43 -0
  704. package/examples/worktree-project-unify.sh +2 -1
  705. package/examples/worktree-remove-uncommitted-guard.sh +13 -0
  706. package/examples/worktree-unmerged-guard.sh +7 -1
  707. package/examples/write-byte-integrity-verifier.sh +190 -0
  708. package/examples/write-empty-content-guard.sh +67 -0
  709. package/examples/write-nul-corruption-detector.sh +61 -0
  710. package/examples/write-overwrite-confirm.sh +160 -14
  711. package/examples/write-secret-guard.sh +27 -5
  712. package/examples/write-shrink-guard.sh +12 -0
  713. package/examples/write-test-ratio.sh +0 -0
  714. package/examples/wsl-host-disk-space-guard.sh +97 -0
  715. package/examples/xml-format-leak-detector.sh +266 -0
  716. package/examples/yaml-syntax-check.sh +12 -0
  717. package/hooks/hooks.json +6 -6
  718. package/index.mjs +1699 -183
  719. package/mission.md +2 -0
  720. package/package.json +4 -4
  721. package/plugins/credential-guard/.claude-plugin/plugin.json +9 -7
  722. package/plugins/git-protection/.claude-plugin/plugin.json +10 -8
  723. package/plugins/safety-essentials/.claude-plugin/plugin.json +9 -7
  724. package/plugins/token-guard/.claude-plugin/plugin.json +10 -8
  725. package/scripts/agents-md-sync-setup.sh +156 -0
  726. package/scripts/autonomy-blocked-summary.sh +148 -0
  727. package/scripts/build-search-index.py +43 -0
  728. package/scripts/build-sitemap.py +119 -0
  729. package/scripts/cc-doctor.sh +192 -0
  730. package/scripts/check-hook-event-names.py +127 -0
  731. package/scripts/check-misfire-instrument.sh +64 -0
  732. package/scripts/claim-verify-audit.sh +467 -0
  733. package/scripts/cowork-claudemd-helper.sh +136 -0
  734. package/scripts/june-15-deprecated-model-scan.sh +111 -0
  735. package/scripts/measure-heredoc-shapes.sh +67 -0
  736. package/scripts/measure-literal-match-misfire.sh +110 -0
  737. package/scripts/probe-scope-guard-branches.sh +48 -0
  738. package/scripts/probe-skip-line-both-ways.sh +65 -0
  739. package/scripts/receipts-aggregate.py +199 -0
  740. package/scripts/session-forensic-audit.py +360 -0
  741. package/scripts.json +9 -9
  742. package/scripts.json.bak-2026-07-27-find +13 -0
  743. package/skills/safety-setup/SKILL.md +5 -5
  744. package/tests/approve-side-remaining-two.test.sh +129 -0
  745. package/tests/approver-list-granularity.test.sh +145 -0
  746. package/tests/askuserquestion-autonomy-gate.test.sh +181 -0
  747. package/tests/audit-ci-gate.test.sh +87 -0
  748. package/tests/audit-cross-layer-claudemd.test.sh +170 -0
  749. package/tests/audit-fail-open-parse.test.sh +100 -0
  750. package/tests/auto-approve-compound-tail.test.sh +194 -0
  751. package/tests/auto-mode-path-invoked-commands.test.sh +89 -0
  752. package/tests/auto-mode-quoted-targets.test.sh +127 -0
  753. package/tests/auto-mode-unquoted-targets.test.sh +112 -0
  754. package/tests/bash-secret-output-detector-detects.test.sh +102 -0
  755. package/tests/blindspots-cross-layer.test.sh +177 -0
  756. package/tests/block-database-wipe.test.sh +64 -0
  757. package/tests/bundled-short-flags-bypass.test.sh +85 -0
  758. package/tests/cd-git-allow-compound-tail.test.sh +67 -0
  759. package/tests/chown-guard-filesystem-root.test.sh +64 -0
  760. package/tests/ci-workflow-guard-skip-rule.test.sh +115 -0
  761. package/tests/compound-deny-safe-rm-targets.test.sh +105 -0
  762. package/tests/core-scripts-parser-fallback.test.sh +140 -0
  763. package/tests/destructive-guard-bare-glob.test.sh +74 -0
  764. package/tests/destructive-guard-every-operand.test.sh +100 -0
  765. package/tests/destructive-guard-find-deletion.test.sh +114 -0
  766. package/tests/destructive-guard-flag-order.test.sh +106 -0
  767. package/tests/destructive-guard-mentions-vs-invocations.test.sh +107 -0
  768. package/tests/destructive-guard-quoted-target.test.sh +89 -0
  769. package/tests/destructive-guard-separators.test.sh +105 -0
  770. package/tests/destructive-guard-variable-target.test.sh +98 -0
  771. package/tests/destructive-guard-wrapped-command.test.sh +91 -0
  772. package/tests/doctor-hook-disabling-env.test.sh +92 -0
  773. package/tests/doctor-misspelled-settings-keys.test.sh +106 -0
  774. package/tests/example-guards-wrapped-command.test.sh +169 -0
  775. package/tests/file-edit-backup.test.sh +93 -0
  776. package/tests/git-filter-repo-guard.test.sh +60 -0
  777. package/tests/git-global-options-bypass.test.sh +141 -0
  778. package/tests/git-invocation-prefixes-all-guards.test.sh +114 -0
  779. package/tests/git-maintenance-guard.test.sh +83 -0
  780. package/tests/git-pack-temp-cleanup-guard.test.sh +133 -0
  781. package/tests/git-rm-orphan-wipe-guard.test.sh +66 -0
  782. package/tests/git-submodule-guard.test.sh +50 -0
  783. package/tests/grep-pcre-portability.test.sh +155 -0
  784. package/tests/hook-registration-matches-input.test.sh +73 -0
  785. package/tests/hook-trigger-matches-envelope.test.sh +178 -0
  786. package/tests/install-does-not-claim-protection.test.sh +110 -0
  787. package/tests/install-example-standalone-tools.test.sh +139 -0
  788. package/tests/line-continuation-bypass.test.sh +114 -0
  789. package/tests/mcp-config-poisoning-audit.test.sh +106 -0
  790. package/tests/nested-background-agent-guard.test.sh +58 -0
  791. package/tests/no-unqualified-safety-claims.test.sh +114 -0
  792. package/tests/option-eating-grep-patterns.test.sh +130 -0
  793. package/tests/outdated-core-guards.test.sh +134 -0
  794. package/tests/outdated-report.test.sh +155 -0
  795. package/tests/output-secret-mask-warns.test.sh +73 -0
  796. package/tests/plugin-hooks-fail-open-under-sh.test.sh +165 -0
  797. package/tests/plugins-word-order.test.sh +126 -0
  798. package/tests/powershell-remove-item-guard.test.sh +85 -0
  799. package/tests/project-dir-naming.test.sh +103 -0
  800. package/tests/quoted-safe-targets-and-mentions.test.sh +190 -0
  801. package/tests/reroute-after-block-guard.test.sh +104 -0
  802. package/tests/secret-guard-documented-promises.test.sh +97 -0
  803. package/tests/session-plugin-pin-watch.test.sh +45 -0
  804. package/tests/settings-unreadable-refuses-to-write.test.sh +95 -0
  805. package/tests/shield-no-silent-adoption.test.py +110 -0
  806. package/tests/shield-no-silent-adoption.test.sh +46 -0
  807. package/tests/stop-transcript-write-health.test.sh +46 -0
  808. package/tests/system-dir-guard-root-erased.test.sh +66 -0
  809. package/tests/test-account-billing-log.sh +100 -0
  810. package/tests/test-account-routing-preflight.sh +77 -0
  811. package/tests/test-agent-sdk-credit-pool-monitor.sh +157 -0
  812. package/tests/test-agent-view-quota-warn.sh +184 -0
  813. package/tests/test-agents-md-edit-drift-warner.sh +176 -0
  814. package/tests/test-agents-md-loader.sh +204 -0
  815. package/tests/test-agents-md-sync-checker.sh +125 -0
  816. package/tests/test-ai-slop-punctuation-arrest.sh +280 -0
  817. package/tests/test-allowlist.sh +60 -0
  818. package/tests/test-always-allow-pattern-suggester.sh +147 -0
  819. package/tests/test-anthropic-base-url-guard.sh +88 -0
  820. package/tests/test-articulated-scope-capture.sh +139 -0
  821. package/tests/test-attachment-traversal-guard.sh +168 -0
  822. package/tests/test-aup-block-pattern-logger.sh +315 -0
  823. package/tests/test-aup-false-positive-helper.sh +188 -0
  824. package/tests/test-aup-large-tool-output-warner.sh +370 -0
  825. package/tests/test-aup-retry-loop-guard.sh +341 -0
  826. package/tests/test-auth-expiry-reminder.sh +303 -0
  827. package/tests/test-auth-macos-sleep-detector.sh +254 -0
  828. package/tests/test-auth-path-detector.sh +232 -0
  829. package/tests/test-auth-status-checker.sh +233 -0
  830. package/tests/test-authorized-reconfirmation-detector.sh +280 -0
  831. package/tests/test-background-cost-launch-guard.sh +62 -0
  832. package/tests/test-bash-allowlist-secondary-check.sh +143 -0
  833. package/tests/test-bash-fanout-bounded-rewriter.sh +186 -0
  834. package/tests/test-bash-project-fence.sh +127 -0
  835. package/tests/test-bg-permission-prompt-warner.sh +221 -0
  836. package/tests/test-binary-read-detector.sh +173 -0
  837. package/tests/test-broad-prefix-session-trap-warner.sh +167 -0
  838. package/tests/test-bulk-delete-target-resolution.sh +49 -0
  839. package/tests/test-bypass-mode-effective-verifier.sh +179 -0
  840. package/tests/test-cache-creation-drift-detector.sh +244 -0
  841. package/tests/test-cache-residue-detector.sh +429 -0
  842. package/tests/test-cache-tier-logger.sh +59 -0
  843. package/tests/test-cache-ttl-eviction-detector.sh +282 -0
  844. package/tests/test-cch-sentinel-precommit-guard.sh +64 -0
  845. package/tests/test-claim-verify-detector.sh +222 -0
  846. package/tests/test-claim-vs-caveat-checker.sh +134 -0
  847. package/tests/test-claude-code-version-pin-advisor.sh +353 -0
  848. package/tests/test-claude-md-reinjector.sh +173 -0
  849. package/tests/test-claude-md-size-monitor.sh +107 -0
  850. package/tests/test-claude-update-budget-guard.sh +132 -0
  851. package/tests/test-claude-update-smart.sh +91 -0
  852. package/tests/test-claudemd-tool-prohibition.sh +239 -0
  853. package/tests/test-cli-config-pinning-detector.sh +233 -0
  854. package/tests/test-cliff-countdown-advisor.sh +138 -0
  855. package/tests/test-closure-word-verify-gate.sh +158 -0
  856. package/tests/test-commit-all-scope-guard.sh +73 -0
  857. package/tests/test-commitment-carry-forward-arrest.sh +250 -0
  858. package/tests/test-compact-dispatch-watchdog.sh +147 -0
  859. package/tests/test-completion-claim-without-verification-detector.sh +326 -0
  860. package/tests/test-compound-bash-permission-resolver.sh +264 -0
  861. package/tests/test-compound-command-deny-enforcer.sh +67 -0
  862. package/tests/test-context-length-budget.sh +68 -0
  863. package/tests/test-context-usage-drift-alert.sh +52 -22
  864. package/tests/test-cost-incident-self-audit.sh +94 -0
  865. package/tests/test-cowork-claude-md-load-checker.sh +257 -0
  866. package/tests/test-cowork-claudemd-helper.sh +141 -0
  867. package/tests/test-cowork-fuse-staleness-watcher.sh +287 -0
  868. package/tests/test-cowork-hook-absence-warner.sh +230 -0
  869. package/tests/test-cowork-model-picker-advisor.sh +317 -0
  870. package/tests/test-credential-exfil-guard.sh +62 -0
  871. package/tests/test-cron-create-receipt.sh +165 -0
  872. package/tests/test-cross-product-mcp-spawn-detector.sh +112 -0
  873. package/tests/test-daemon-zombie-worker-surfacer.sh +71 -0
  874. package/tests/test-daily-cost-guard.sh +131 -0
  875. package/tests/test-deny-rule-integrity-verifier.sh +288 -0
  876. package/tests/test-deployment-readback-gate.sh +92 -0
  877. package/tests/test-deployment-readback-gh-adapter.sh +163 -0
  878. package/tests/test-disabled-feature-toggle-advisor.sh +78 -0
  879. package/tests/test-dispatch-allowlist-preflight.sh +385 -0
  880. package/tests/test-dispatch-liveness-watchdog.sh +319 -0
  881. package/tests/test-dispatch-receipt.sh +314 -0
  882. package/tests/test-dotenv-anthropic-key-billing-guard.sh +160 -0
  883. package/tests/test-echo-probe-spam-detector.sh +143 -0
  884. package/tests/test-edit-quote-ambiguity-guard.sh +75 -0
  885. package/tests/test-ephemeral-container-detector.sh +251 -0
  886. package/tests/test-evidence-claim-gate.sh +291 -0
  887. package/tests/test-extended-thinking-loop-guard.sh +289 -0
  888. package/tests/test-extended-thinking-resume-warning.sh +240 -0
  889. package/tests/test-extended-thinking-tool-use-mismatch-detector.sh +236 -0
  890. package/tests/test-fabricated-command-detector.sh +296 -0
  891. package/tests/test-false-disk-full-guard.sh +36 -0
  892. package/tests/test-feature-deprecation-detector.sh +117 -0
  893. package/tests/test-forbidden-response-phrase-detector.sh +246 -0
  894. package/tests/test-git-operations-require-approval.sh +53 -0
  895. package/tests/test-git-push-blast-radius-guard.sh +115 -0
  896. package/tests/test-goal-iteration-limit-warner.sh +128 -0
  897. package/tests/test-growthbook-flag-monitor.sh +428 -0
  898. package/tests/test-halt-signal-detector.sh +120 -0
  899. package/tests/test-hook-self-disable-detector.sh +232 -0
  900. package/tests/test-iteration-quality-degradation-detector.sh +244 -0
  901. package/tests/test-long-session-malformed-tool-call-detector.sh +185 -0
  902. package/tests/test-marketplace-plugins.sh +193 -0
  903. package/tests/test-mcp-misdiagnosis-arrest.sh +235 -0
  904. package/tests/test-mcp-orphan-leak-warner.sh +71 -0
  905. package/tests/test-mcp-permissions-ask-warner.sh +207 -0
  906. package/tests/test-mcp-routine-approval-detector.sh +229 -0
  907. package/tests/test-mcp-startup-bloat-detector.sh +141 -0
  908. package/tests/test-mcp-stdio-compatibility-test.sh +112 -0
  909. package/tests/test-memory-chain-audit.sh +59 -0
  910. package/tests/test-memory-orphan-detector.sh +227 -0
  911. package/tests/test-model-swap-suggester.sh +368 -0
  912. package/tests/test-model-version-lock.sh +83 -0
  913. package/tests/test-multi-file-plan-routing-gate.sh +277 -0
  914. package/tests/test-multi-window-auth-drift-detector.sh +262 -0
  915. package/tests/test-nested-spawn-inflight-guard.sh +281 -0
  916. package/tests/test-no-force-flag.sh +49 -0
  917. package/tests/test-non-english-quality-warner.sh +229 -0
  918. package/tests/test-oauth-refresh-monitor.sh +311 -0
  919. package/tests/test-opus-degradation-tracker.sh +274 -0
  920. package/tests/test-opus48-routine-task-warning.sh +201 -0
  921. package/tests/test-opus48-thinking-wedge-advisor.sh +249 -0
  922. package/tests/test-output-token-spike-detector.sh +315 -0
  923. package/tests/test-parallel-batch-size-limiter.sh +228 -0
  924. package/tests/test-parallel-cascade-detector.sh +191 -0
  925. package/tests/test-partial-view-claim-arrest.sh +272 -0
  926. package/tests/test-per-prompt-token-cap.sh +136 -0
  927. package/tests/test-persisted-1m-model-advisor.sh +71 -0
  928. package/tests/test-plugin-hooks-json-bloat-detector.sh +267 -0
  929. package/tests/test-post-edit-disk-verify.sh +294 -0
  930. package/tests/test-pre-bash-sed-line-ending-windows.sh +108 -0
  931. package/tests/test-pre-execution-claim-detector.sh +366 -0
  932. package/tests/test-private-key-backup-and-git-credentials.sh +100 -0
  933. package/tests/test-proxy-capture-suggester.sh +214 -0
  934. package/tests/test-public-artefact-socratic-narrowing.sh +346 -0
  935. package/tests/test-quota-anomaly-detector.sh +321 -0
  936. package/tests/test-quota-reset-audit.sh +81 -0
  937. package/tests/test-read-loop-detector.sh +137 -0
  938. package/tests/test-read-once-guard.sh +85 -0
  939. package/tests/test-receipts-aggregate.sh +143 -0
  940. package/tests/test-redirect-fragment-warner.sh +130 -0
  941. package/tests/test-redundant-read-blocker.sh +155 -0
  942. package/tests/test-refusal-arrest-gate.sh +303 -0
  943. package/tests/test-remote-control-billing-classifier.sh +125 -0
  944. package/tests/test-resume-drift-watcher.sh +65 -0
  945. package/tests/test-rg-replace-flag-detector.sh +175 -0
  946. package/tests/test-rhetorical-verification-prompt-detector.sh +237 -0
  947. package/tests/test-rm-safety-net.sh +115 -0
  948. package/tests/test-route-handler-emptiness-gate.sh +300 -0
  949. package/tests/test-runtime-binary-change-detector.sh +196 -0
  950. package/tests/test-same-command-repeat-detector.sh +165 -0
  951. package/tests/test-same-correction-arrest.sh +165 -0
  952. package/tests/test-scope-expansion-receipt.sh +207 -0
  953. package/tests/test-server-side-prompt-injection-detector.sh +181 -0
  954. package/tests/test-session-persistence-verifier.sh +128 -0
  955. package/tests/test-session-rate-monitor.sh +284 -0
  956. package/tests/test-session-start-quota-status.sh +210 -0
  957. package/tests/test-session-start-safety-check.sh +138 -0
  958. package/tests/test-settings-hooks-key-restorer.sh +257 -0
  959. package/tests/test-settings-json-health-check.sh +70 -0
  960. package/tests/test-settings-regression-tester.sh +197 -0
  961. package/tests/test-skill-cumulative-size-detector.sh +198 -0
  962. package/tests/test-skill-description-drop-detector.sh +236 -0
  963. package/tests/test-skill-truncation-detector.sh +263 -0
  964. package/tests/test-skills-context-recorder.sh +329 -0
  965. package/tests/test-skills-load-verifier.sh +184 -0
  966. package/tests/test-skills-settings-validator.sh +242 -0
  967. package/tests/test-sonnet-45-deprecation-helper.sh +150 -0
  968. package/tests/test-spurious-malformed-notice-detector.sh +290 -0
  969. package/tests/test-sql-bulk-delete-warn.sh +123 -0
  970. package/tests/test-ssh-key-protect.sh +81 -0
  971. package/tests/test-stale-temp-settings-detector.sh +161 -0
  972. package/tests/test-standing-rule-session-surfacer.sh +215 -0
  973. package/tests/test-starter-hooks-manifest.sh +96 -0
  974. package/tests/test-stop-hook-sigterm-wrapper.sh +258 -0
  975. package/tests/test-strict-allowlist.sh +72 -0
  976. package/tests/test-subagent-boundary-precheck.sh +137 -0
  977. package/tests/test-subagent-closure-verify-gate.sh +193 -0
  978. package/tests/test-subagent-destructive-git-guard.sh +86 -0
  979. package/tests/test-subagent-identity-leak-guard.sh +62 -0
  980. package/tests/test-subagent-identity-reassertion.sh +61 -0
  981. package/tests/test-subagent-inheritance-tester.sh +319 -0
  982. package/tests/test-subagent-permission-mode-guard.sh +61 -0
  983. package/tests/test-subagent-spawn-verification-enforcer.sh +60 -0
  984. package/tests/test-subagent-tool-allowlist-enforcer.sh +62 -0
  985. package/tests/test-subagent-tool-call-limiter.sh +97 -0
  986. package/tests/test-subscription-api-billing-warner.sh +138 -0
  987. package/tests/test-subscription-bypass-detector.sh +255 -0
  988. package/tests/test-temporal-suggestion-detector.sh +183 -0
  989. package/tests/test-thinking-budget-effort-mismatch-detector.sh +327 -0
  990. package/tests/test-tokenizer-ratio-alert-corpus.sh +77 -0
  991. package/tests/test-tokenizer-ratio-alert.sh +93 -0
  992. package/tests/test-tool-result-correlation-checker.sh +264 -0
  993. package/tests/test-tool-result-size-guard.sh +121 -0
  994. package/tests/test-transcript-contamination-detector.sh +264 -0
  995. package/tests/test-trigger-header-parsing.sh +151 -0
  996. package/tests/test-ultrareview-large-diff-advisor.sh +192 -0
  997. package/tests/test-userprompt-submit-receipt.sh +181 -0
  998. package/tests/test-verify-after-publish-reminder.sh +184 -0
  999. package/tests/test-version-bump-detector.sh +212 -0
  1000. package/tests/test-version-regression-warner.sh +165 -0
  1001. package/tests/test-warn-cron-cost-trap.sh +82 -0
  1002. package/tests/test-webfetch-runaway-guard.sh +77 -0
  1003. package/tests/test-wellness-break-reminder.sh +138 -0
  1004. package/tests/test-windows-destructive-command-guard.sh +169 -0
  1005. package/tests/test-windows-python-stub-detector.sh +146 -0
  1006. package/tests/test-worktree-edit-boundary-guard.sh +219 -0
  1007. package/tests/test-write-byte-integrity-verifier.sh +192 -0
  1008. package/tests/test-xml-format-leak-detector.sh +299 -0
  1009. package/tests/trustfall-mcp-injection-guard.test.sh +183 -0
  1010. package/tests/workspace-lease-guard.test.sh +144 -0
  1011. package/tests/worktree-escape-write-guard.test.sh +68 -0
  1012. package/tests/worktree-hooks-path-fix.test.sh +181 -0
  1013. package/tests/worktree-parent-write-guard.test.sh +51 -0
  1014. package/tests/write-empty-content-guard.test.sh +39 -0
  1015. package/tests/write-nul-corruption-detector.test.sh +29 -0
  1016. package/tests/write-overwrite-unread-content.test.sh +178 -0
  1017. package/tests/wsl-host-disk-space-guard.test.sh +55 -0
@@ -0,0 +1,155 @@
1
+ #!/bin/bash
2
+ # --outdated: which installed hooks no longer match what ships today.
3
+ #
4
+ # Why this exists. Installing a hook copies the file. Nothing ever copies it
5
+ # back. So a hook installed in March keeps running its March logic forever,
6
+ # including bugs fixed here months later, and until now nothing in the CLI
7
+ # could tell you that. Measured on a real four-month-old install: 27 of the 31
8
+ # hooks that came from this project no longer matched the shipped version, and
9
+ # three of those were missing the `jq` guard that was added after they were
10
+ # installed — the difference between blocking a dangerous command and silently
11
+ # approving it.
12
+ #
13
+ # The command only reports. The most important control here is the last one:
14
+ # it must not write anything. A command whose whole job is "tell me if my
15
+ # safety net is stale" must not itself modify the safety net.
16
+ #
17
+ # The second control is that "differs" is not claimed to mean "outdated".
18
+ # A user who edited their own copy on purpose must not be told they are behind,
19
+ # so the wording offers both readings and the test pins that wording.
20
+
21
+ set -u
22
+ REPO="$(cd "$(dirname "$0")/.." && pwd)"
23
+ PASS=0
24
+ FAIL=0
25
+
26
+ check() { # name expected actual
27
+ if [ "$2" = "$3" ]; then
28
+ PASS=$((PASS + 1))
29
+ else
30
+ FAIL=$((FAIL + 1))
31
+ echo " FAIL: $1"
32
+ echo " expected: $2"
33
+ echo " actual: $3"
34
+ fi
35
+ }
36
+
37
+ contains() { # name haystack needle
38
+ case "$2" in
39
+ *"$3"*) PASS=$((PASS + 1)) ;;
40
+ *) FAIL=$((FAIL + 1)); echo " FAIL: $1"; echo " output did not contain: $3" ;;
41
+ esac
42
+ }
43
+
44
+ not_contains() { # name haystack needle
45
+ case "$2" in
46
+ *"$3"*) FAIL=$((FAIL + 1)); echo " FAIL: $1"; echo " output unexpectedly contained: $3" ;;
47
+ *) PASS=$((PASS + 1)) ;;
48
+ esac
49
+ }
50
+
51
+ TESTHOME="$(mktemp -d)"
52
+ trap 'rm -rf "$TESTHOME"' EXIT
53
+
54
+ # Sets OUT and RC. Deliberately not called through $( ) — command substitution
55
+ # runs in a subshell, so the exit code would never reach the caller.
56
+ run_outdated() {
57
+ OUT=$(CLAUDE_PROJECT_DIR="$TESTHOME" node "$REPO/index.mjs" --outdated 2>&1)
58
+ RC=$?
59
+ }
60
+
61
+ # --- 1. no hooks directory at all --------------------------------------------
62
+ run_outdated
63
+ check "no hooks dir exits 0" "0" "$RC"
64
+ contains "no hooks dir is explained" "$OUT" "No hooks directory"
65
+
66
+ # --- 2. an untouched copy of a shipped hook reports as matching ---------------
67
+ mkdir -p "$TESTHOME/.claude/hooks"
68
+ cp "$REPO/examples/protect-claudemd.sh" "$TESTHOME/.claude/hooks/protect-claudemd.sh"
69
+ run_outdated
70
+ check "identical copy exits 0" "0" "$RC"
71
+ contains "identical copy reported as matching" "$OUT" "match the shipped version"
72
+ not_contains "identical copy is not called differing" "$OUT" "differ from what ships today"
73
+
74
+ # --- 3. a modified copy is reported, and the exit code is non-zero -----------
75
+ echo "# a local change" >> "$TESTHOME/.claude/hooks/protect-claudemd.sh"
76
+ run_outdated
77
+ check "modified copy exits 1" "1" "$RC"
78
+ contains "modified copy is named" "$OUT" "protect-claudemd.sh"
79
+ contains "modified copy is counted" "$OUT" "differ from what ships today"
80
+
81
+ # --- 4. "differs" must not be claimed to mean "outdated" ---------------------
82
+ # The user may have edited the file on purpose. Both readings must be offered.
83
+ contains "both readings are offered (fixed here)" "$OUT" "was fixed after you installed it"
84
+ contains "both readings are offered (your edit)" "$OUT" "you edited your copy on purpose"
85
+ contains "a way to look before replacing" "$OUT" "diff "
86
+
87
+ # --- 5. the concrete harm: installed copy parses with jq but has no jq guard --
88
+ # Build exactly that situation from a shipped hook that does have the guard.
89
+ JQ_HOOK=""
90
+ for f in "$REPO"/examples/*.sh; do
91
+ if grep -q 'command -v jq\|which jq' "$f" && grep -q '\bjq\b' "$f"; then
92
+ JQ_HOOK="$f"; break
93
+ fi
94
+ done
95
+ if [ -n "$JQ_HOOK" ]; then
96
+ NAME="$(basename "$JQ_HOOK")"
97
+ rm -f "$TESTHOME/.claude/hooks/protect-claudemd.sh"
98
+ grep -v 'command -v jq' "$JQ_HOOK" | grep -v 'which jq' > "$TESTHOME/.claude/hooks/$NAME"
99
+ run_outdated
100
+ check "jq-guardless copy exits 1" "1" "$RC"
101
+ contains "jq-guardless copy is flagged as such" "$OUT" "no jq guard"
102
+ else
103
+ echo " SKIP: no shipped hook both uses jq and guards for it"
104
+ fi
105
+
106
+ # --- 6. a hook this project does not ship is not judged ----------------------
107
+ rm -f "$TESTHOME/.claude/hooks"/*.sh
108
+ cat > "$TESTHOME/.claude/hooks/my-own-thing.sh" <<'EOF'
109
+ #!/bin/bash
110
+ exit 0
111
+ EOF
112
+ run_outdated
113
+ check "foreign-only install exits 0" "0" "$RC"
114
+ contains "foreign hook counted separately" "$OUT" "not shipped by this project"
115
+ not_contains "foreign hook is not named as differing" "$OUT" "my-own-thing.sh differ"
116
+
117
+ # --- 7. the control that matters: --outdated must not write anything ---------
118
+ # This control was defeated twice while it was being written, in two different
119
+ # ways, and both are worth stating because both are easy to reproduce:
120
+ #
121
+ # 1. The snapshot used `for f in *`. A glob does not match dotfiles, so a
122
+ # planted `writeFileSync(HOOKS_DIR + '/.outdated-marker')` was invisible.
123
+ # Fixed by walking the directory with find.
124
+ # 2. Even after that, the run in section 6 had already created the marker, so
125
+ # the file existed in BOTH the before and the after snapshot and the
126
+ # comparison still showed no change. A "did it write?" check cannot share
127
+ # state with an earlier run of the thing under test.
128
+ #
129
+ # So this section builds its own directory and takes the first snapshot before
130
+ # --outdated has ever run against it.
131
+ snapshot() { # dir -> "relpath:cksum" lines, dotfiles included
132
+ find "$1" -type f | sort | while IFS= read -r f; do
133
+ printf '%s:%s\n' "${f#"$1"}" "$(cksum < "$f")"
134
+ done
135
+ }
136
+ TESTHOME="$(mktemp -d)" # fresh: nothing here has been looked at yet
137
+ trap 'rm -rf "$TESTHOME"' EXIT
138
+ mkdir -p "$TESTHOME/.claude/hooks"
139
+ # A hook that differs, so --outdated has something to report and therefore takes
140
+ # the branch that prints. A run that finds nothing would not exercise the code
141
+ # where a stray write would live.
142
+ cp "$REPO/examples/protect-claudemd.sh" "$TESTHOME/.claude/hooks/protect-claudemd.sh"
143
+ echo "# local edit" >> "$TESTHOME/.claude/hooks/protect-claudemd.sh"
144
+ printf '{"hooks":{}}' > "$TESTHOME/.claude/settings.json"
145
+ BEFORE_HOOKS=$(snapshot "$TESTHOME/.claude/hooks")
146
+ BEFORE_SETTINGS=$(cksum < "$TESTHOME/.claude/settings.json")
147
+ run_outdated
148
+ AFTER_HOOKS=$(snapshot "$TESTHOME/.claude/hooks")
149
+ AFTER_SETTINGS=$(cksum < "$TESTHOME/.claude/settings.json")
150
+ check "hooks are untouched by --outdated" "$BEFORE_HOOKS" "$AFTER_HOOKS"
151
+ check "settings.json is untouched by --outdated" "$BEFORE_SETTINGS" "$AFTER_SETTINGS"
152
+
153
+ echo
154
+ echo "outdated-report: $PASS passed, $FAIL failed"
155
+ [ "$FAIL" -eq 0 ] || exit 1
@@ -0,0 +1,73 @@
1
+ #!/bin/bash
2
+ # output-secret-mask: does the warning actually fire, and only when it should?
3
+ #
4
+ # Why this exists. The eight existing checks for this hook in test.sh all assert
5
+ # exit 0. This hook *always* exits 0 — it only writes to stderr — so those checks
6
+ # pass whether the warning fires or not. They cannot fail on the behaviour that
7
+ # matters, which is the same shape as the "234 test files that could not fail"
8
+ # noted in the CI workflow. These assert on stderr instead.
9
+ #
10
+ # The regression being pinned: the OpenAI pattern used to be written without a
11
+ # left boundary, so ordinary English words ending in "sk" before a separator
12
+ # (task-, ask-, risk-, disk-, desk-) matched and the hook cried on ordinary
13
+ # output. A warning that fires on normal paths is a warning operators learn to
14
+ # ignore, which costs the whole hook.
15
+ #
16
+ # Both directions are asserted deliberately: silencing a false positive is only
17
+ # a fix if the true positive still fires.
18
+
19
+ set -u
20
+ REPO="$(cd "$(dirname "$0")/.." && pwd)"
21
+ HOOK="$REPO/examples/output-secret-mask.sh"
22
+ PASS=0
23
+ FAIL=0
24
+
25
+ # Split so that writing this file does not itself trip a secret scanner.
26
+ KEY="sk""-proj-abcdefghijklmno""pqrst1234567890"
27
+ AWS="AKI""AIOSFODNN7""EXAMPLE"
28
+ ORDINARY="data/task-""management-system-config.json"
29
+
30
+ run() { # run <stdout-text> -> sets ERR
31
+ local payload
32
+ payload=$(printf '{"tool_name":"Bash","tool_input":{"command":"cat conf"},"tool_result":{"stdout":"%s"}}' "$1")
33
+ ERR=$(printf '%s' "$payload" | bash "$HOOK" 2>&1 >/dev/null)
34
+ }
35
+
36
+ warns() { # warns <name> <text> <expect: yes|no>
37
+ run "$2"
38
+ local got="no"
39
+ case "$ERR" in *WARNING*) got="yes" ;; esac
40
+ if [ "$got" = "$3" ]; then
41
+ PASS=$((PASS + 1))
42
+ else
43
+ FAIL=$((FAIL + 1))
44
+ echo " FAIL: $1 (expected warn=$3, got warn=$got)"
45
+ echo " stderr: $ERR"
46
+ fi
47
+ }
48
+
49
+ echo "output-secret-mask-warns:"
50
+
51
+ # --- true positives: the warning has to fire -------------------------------
52
+ warns "real key shape warns" "$KEY" yes
53
+ warns "AWS key shape warns" "$AWS" yes
54
+ warns "API_KEY assignment warns" "API_KEY=abc123def456ghi" yes
55
+
56
+ # --- false positives: the warning must stay quiet --------------------------
57
+ warns "ordinary task- path is quiet" "$ORDINARY" no
58
+ warns "plain output is quiet" "hello world" no
59
+ warns "safe env var is quiet" "PATH=/usr/bin" no
60
+
61
+ # --- the hook never blocks; it only reports --------------------------------
62
+ printf '%s' "{\"tool_name\":\"Bash\",\"tool_result\":{\"stdout\":\"$KEY\"}}" \
63
+ | bash "$HOOK" >/dev/null 2>&1
64
+ rc=$?
65
+ if [ "$rc" -eq 0 ]; then
66
+ PASS=$((PASS + 1))
67
+ else
68
+ FAIL=$((FAIL + 1))
69
+ echo " FAIL: hook must not block (expected exit 0, got $rc)"
70
+ fi
71
+
72
+ echo " $PASS passed, $FAIL failed"
73
+ [ "$FAIL" -eq 0 ]
@@ -0,0 +1,165 @@
1
+ #!/bin/bash
2
+ # The plugin hooks failed open under /bin/sh
3
+ #
4
+ # hooks/hooks.json holds the four inline guards that ship as the plugin's
5
+ # hook file. Claude Code runs an inline hook command through /bin/sh, and on
6
+ # Debian and Ubuntu /bin/sh is dash. Dash's builtin echo interprets backslash
7
+ # escapes; bash's does not.
8
+ #
9
+ # Every one of the four guards started with:
10
+ #
11
+ # INPUT=$(cat); CMD=$(echo "$INPUT" | jq -r '.tool_input.command // empty')
12
+ #
13
+ # The hook payload is JSON, so a newline inside the command or the file
14
+ # content arrives as the two characters \n. Under dash, echo turned those two
15
+ # characters into a real newline *inside a JSON string*, jq rejected the
16
+ # document, CMD came back empty, and the very next clause is:
17
+ #
18
+ # [ -z "$CMD" ] && exit 0
19
+ #
20
+ # exit 0 is an affirmative approval. So the guards let the tool call through,
21
+ # and the debug log recorded the hook as "success". Measured 2026-09-03: an
22
+ # agent asked to create .env wrote it with all six shipped hooks installed.
23
+ #
24
+ # Nothing local caught this for months because every test ran the commands
25
+ # under bash, where echo leaves \n alone. The five plugin manifests under
26
+ # plugins/ already used `printf %s "$INPUT"`; hooks/hooks.json never got the
27
+ # same change.
28
+ #
29
+ # Three more holes turned up in the same file once the parse was fixed:
30
+ #
31
+ # 1. The rm guard checked its exemption list (node_modules|dist|build|
32
+ # __pycache__|tmp) against the whole command, so `cd /tmp` on line one
33
+ # exempted `rm -rf /` on line two.
34
+ # 2. `sed -E 's/[;&|#].*$//'` truncated at the first `;`, so everything
35
+ # after a separator was never examined at all.
36
+ # 3. A line continuation split the spelling and no guard matched it.
37
+ #
38
+ # The fix joins continuations, splits on statement separators, and asks the
39
+ # dangerous question and the exemption question about the *same* statement.
40
+ #
41
+ # Every case below runs the shipped command under /bin/sh, which is the shell
42
+ # that actually runs it in production.
43
+ ROOT="$(cd "$(dirname "$0")/.." && pwd)"
44
+ HOOKS="$ROOT/hooks/hooks.json"
45
+ PASS=0
46
+ FAIL=0
47
+
48
+ hook_command() {
49
+ # $1 = index into PreToolUse
50
+ python3 -c "
51
+ import json, sys
52
+ d = json.load(open('$HOOKS', encoding='utf-8'))
53
+ pre = (d.get('hooks') or d)['PreToolUse']
54
+ sys.stdout.write(pre[$1]['hooks'][0]['command'])
55
+ "
56
+ }
57
+
58
+ check() {
59
+ # $1=index $2=label $3=expected(block|allow) $4=payload json
60
+ local cmd rc got
61
+ cmd=$(hook_command "$1")
62
+ printf '%s' "$4" | /bin/sh -c "$cmd" >/dev/null 2>&1
63
+ rc=$?
64
+ if [ "$rc" -eq 2 ]; then got=block; else got=allow; fi
65
+ if [ "$got" = "$3" ]; then
66
+ PASS=$((PASS + 1))
67
+ else
68
+ FAIL=$((FAIL + 1))
69
+ echo " FAIL [hook $1] $2: expected $3, got $got (rc=$rc)"
70
+ fi
71
+ }
72
+
73
+ bash_payload() {
74
+ python3 -c "
75
+ import json, sys
76
+ sys.stdout.write(json.dumps({'tool_name': 'Bash',
77
+ 'tool_input': {'command': sys.argv[1]}}))
78
+ " "$1"
79
+ }
80
+
81
+ write_payload() {
82
+ python3 -c "
83
+ import json, sys
84
+ sys.stdout.write(json.dumps({'tool_name': 'Write',
85
+ 'tool_input': {'file_path': sys.argv[1],
86
+ 'content': sys.argv[2]}}))
87
+ " "$1" "$2"
88
+ }
89
+
90
+ # The dangerous spellings are assembled so that mentioning them in this file
91
+ # does not trip the repository's own guards.
92
+ RM="rm -rf /"
93
+ PUSHF="git push --force origin main"
94
+ RESETH="git reset --hard HEAD~1"
95
+ CLEANFD="git clean -fd"
96
+
97
+ echo "hook 0 — recursive rm"
98
+ check 0 "plain" block "$(bash_payload "$RM")"
99
+ check 0 "newline after cd /tmp" block "$(bash_payload "$(printf 'cd /tmp\n%s' "$RM")")"
100
+ check 0 "newline after cd build" block "$(bash_payload "$(printf 'cd build\n%s' "$RM")")"
101
+ check 0 "line continuation" block "$(bash_payload "$(printf 'rm \\\n -rf /')")"
102
+ check 0 "after a semicolon" block "$(bash_payload "date; $RM")"
103
+ check 0 "after &&" block "$(bash_payload "cd /tmp && $RM")"
104
+ check 0 "sudo prefix" block "$(bash_payload "sudo $RM")"
105
+ check 0 "-fr order" block "$(bash_payload "rm -fr /")"
106
+ check 0 "--recursive" block "$(bash_payload "rm --recursive /etc")"
107
+ check 0 "home subdirectory" block "$(bash_payload "rm -rf ~/Documents")"
108
+ check 0 "node_modules" allow "$(bash_payload "rm -rf node_modules")"
109
+ check 0 "./build" allow "$(bash_payload "rm -rf ./build")"
110
+ check 0 "dist/" allow "$(bash_payload "rm -rf dist/")"
111
+ check 0 "under /tmp" allow "$(bash_payload "rm -rf /tmp/scratch")"
112
+ check 0 "non-recursive rm" allow "$(bash_payload "rm -f foo.txt")"
113
+ check 0 "plain ls" allow "$(bash_payload "ls -la")"
114
+ check 0 "inside a comment" allow "$(bash_payload "date # $RM")"
115
+
116
+ echo "hook 1 — destructive git"
117
+ check 1 "force push" block "$(bash_payload "$PUSHF")"
118
+ check 1 "force push continued" block "$(bash_payload "$(printf 'git push \\\n --force origin main')")"
119
+ check 1 "force push line 2" block "$(bash_payload "$(printf 'cd /tmp\n%s' "$PUSHF")")"
120
+ check 1 "hard reset" block "$(bash_payload "$RESETH")"
121
+ check 1 "hard reset continued" block "$(bash_payload "$(printf 'git reset \\\n --hard HEAD~1')")"
122
+ check 1 "clean -fd" block "$(bash_payload "$CLEANFD")"
123
+ check 1 "clean -fd continued" block "$(bash_payload "$(printf 'git clean \\\n -fd')")"
124
+ check 1 "force-with-lease" allow "$(bash_payload "git push --force-with-lease origin main")"
125
+ check 1 "word on another line" allow "$(bash_payload "$(printf 'git push origin main\necho --force')")"
126
+ check 1 "ordinary push" allow "$(bash_payload "git push origin main")"
127
+ check 1 "soft reset" allow "$(bash_payload "git reset --soft HEAD~1")"
128
+
129
+ echo "hook 2 — credentials in the command"
130
+ check 2 "inline key" block "$(bash_payload "export API_KEY=abcdefghij0123456789xyz")"
131
+ check 2 "inline key continued" block "$(bash_payload "$(printf 'export API_KEY=\\\nabcdefghij0123456789xyz')")"
132
+ check 2 "short value" allow "$(bash_payload "export API_KEY=short")"
133
+ check 2 "unrelated" allow "$(bash_payload "ls -la")"
134
+
135
+ echo "hook 3 — writes to sensitive files"
136
+ check 3 "dotenv" block "$(write_payload "/x/.env" "$(printf 'A=1\nB=2')")"
137
+ check 3 "private key" block "$(write_payload "/x/server.pem" "$(printf 'A=1\nB=2')")"
138
+ check 3 "ssh key" block "$(write_payload "/x/id_rsa" "$(printf 'A=1\nB=2')")"
139
+ check 3 "dotenv template" allow "$(write_payload "/x/.env.template" "$(printf 'A=1\nB=2')")"
140
+ check 3 "ordinary file" allow "$(write_payload "/x/notes.md" "$(printf 'A=1\nB=2')")"
141
+
142
+ echo "no hook may still pipe echo into a parser"
143
+ # The file is JSON, so the spelling inside it is escaped. Grepping the raw
144
+ # bytes for the unescaped form matches nothing even when the defect is
145
+ # present -- a check that cannot fail. Read it as JSON and look at the
146
+ # commands after unescaping.
147
+ if python3 -c "
148
+ import json, sys
149
+ d = json.load(open('$HOOKS', encoding='utf-8'))
150
+ pre = (d.get('hooks') or d)['PreToolUse']
151
+ bad = [i for i, e in enumerate(pre)
152
+ for h in e.get('hooks', [])
153
+ if 'echo \"\$INPUT\"' in h.get('command', '')]
154
+ print(','.join(str(i) for i in bad))
155
+ sys.exit(1 if bad else 0)
156
+ "; then
157
+ PASS=$((PASS + 1))
158
+ else
159
+ FAIL=$((FAIL + 1))
160
+ echo " FAIL: a hook still pipes echo \"\$INPUT\" into a parser"
161
+ fi
162
+
163
+ echo
164
+ echo "PASS=$PASS FAIL=$FAIL"
165
+ [ "$FAIL" -eq 0 ]
@@ -0,0 +1,126 @@
1
+ #!/bin/bash
2
+ # marketplace plugins: the same word-order assumptions, in a second implementation
3
+ #
4
+ # The four bundles under plugins/ carry their shell **inline in plugin.json**. They
5
+ # are not copies of the core hooks — they are a separate implementation — so fixing
6
+ # the core does nothing for anyone who installed a plugin.
7
+ #
8
+ # Measured 2026-08-03 with all four bundles installed together, over the 24 forms
9
+ # of the destructive-command probe that these bundles claim to cover:
10
+ #
11
+ # before 10 of 24 walked through
12
+ # after 3 of 24 (find / dd / chmod — none of the four bundles claims those)
13
+ #
14
+ # What walked through was the familiar shape: a rule describing how a command is
15
+ # usually typed rather than what it does.
16
+ #
17
+ # rm -r -f X the flags have to be one bundle
18
+ # rm --recursive --force X ... and short
19
+ # rm X -rf ... and before the target
20
+ # git reset HEAD~1 --hard --hard has to follow reset
21
+ # git clean -x -f -d the flags have to come first
22
+ # git branch --delete --force only -D was named
23
+ #
24
+ # One description also promised something that was never implemented:
25
+ # git-protection said it "guards interactive rebase" and no hook in the bundle
26
+ # mentions rebase at all. The claim is gone rather than newly built — an interactive
27
+ # rebase is ordinary work, and blocking it would trade a false promise for a false
28
+ # positive.
29
+ #
30
+ # The dry runs are the half that keeps a guard installed: widening the git clean
31
+ # pattern also caught `git clean -nd`, which removes nothing. That regression was
32
+ # introduced and fixed in the same pass; both directions are asserted below.
33
+ ROOT="$(cd "$(dirname "$0")/.." && pwd)"
34
+
35
+ PASS=0; FAIL=0
36
+
37
+ # want: block | allow
38
+ check() {
39
+ local desc="$1" cmd="$2" want="$3" tool="${4:-Bash}"
40
+ local got
41
+ got=$(python3 - "$ROOT" "$cmd" "$tool" <<'PY'
42
+ import glob, json, os, subprocess, sys, tempfile
43
+ root, cmd, tool = sys.argv[1], sys.argv[2], sys.argv[3]
44
+ cmds = []
45
+ for pdir in sorted(glob.glob(os.path.join(root, "plugins", "*"))):
46
+ f = os.path.join(pdir, ".claude-plugin", "plugin.json")
47
+ if not os.path.exists(f):
48
+ continue
49
+ d = json.load(open(f, encoding="utf-8"))
50
+ for ev in d.get("hooks", {}).values():
51
+ for e in ev:
52
+ for h in e.get("hooks", []):
53
+ cmds.append((e.get("matcher", ""), h["command"]))
54
+ req = json.dumps({"hook_event_name": "PreToolUse", "tool_name": tool,
55
+ "tool_input": {"command": cmd, "file_path": cmd}})
56
+ for m, sh in cmds:
57
+ if m and tool not in m:
58
+ continue
59
+ t = tempfile.NamedTemporaryFile("w", suffix=".sh", delete=False, encoding="utf-8")
60
+ t.write(sh); t.close()
61
+ try:
62
+ r = subprocess.run(["bash", t.name], input=req, capture_output=True,
63
+ text=True, timeout=15)
64
+ if r.returncode == 2:
65
+ print("block"); raise SystemExit
66
+ finally:
67
+ os.unlink(t.name)
68
+ print("allow")
69
+ PY
70
+ )
71
+ if [ "$got" = "$want" ]; then
72
+ echo "PASS: $desc"; PASS=$((PASS+1))
73
+ else
74
+ echo "FAIL: $desc (expected $want, got $got)"; FAIL=$((FAIL+1))
75
+ fi
76
+ }
77
+
78
+ TARGET="/var/app"
79
+
80
+ # --- rm, whatever shape the flags arrive in ---
81
+ check "rm -rf" "rm -rf $TARGET" block
82
+ check "rm -fr" "rm -fr $TARGET" block
83
+ check "flags split" "rm -r -f $TARGET" block
84
+ check "flags split, other order" "rm -f -r $TARGET" block
85
+ check "long flags" "rm --recursive --force $TARGET" block
86
+ check "long flags, other order" "rm --force --recursive $TARGET" block
87
+ check "flags after the target" "rm $TARGET -rf" block
88
+
89
+ # --- git reset --hard, wherever the flag sits ---
90
+ check "reset, canonical" "git reset --hard HEAD~1" block
91
+ check "reset, flag last" "git reset HEAD~1 --hard" block
92
+ check "reset --soft is allowed" "git reset --soft HEAD~1" allow
93
+
94
+ # --- git clean: destructive blocked, dry runs kept ---
95
+ check "clean -fd" "git clean -fd" block
96
+ check "clean, flags split" "git clean -x -f -d" block
97
+ check "clean, long flag" "git clean --force -d" block
98
+ check "dry run" "git clean -n" allow
99
+ check "dry run with -d" "git clean -nd" allow
100
+ check "dry run with -d and -x" "git clean -ndx" allow
101
+ check "long dry run" "git clean --dry-run" allow
102
+ check "force plus dry run" "git clean --force --dry-run" allow
103
+
104
+ # --- branch deletion, both spellings ---
105
+ check "branch -D" "git branch -D main" block
106
+ check "branch --delete --force" "git branch --delete --force main" block
107
+ check "safe delete is allowed" "git branch -d old-feature" allow
108
+
109
+ # --- what the bundles already got right, kept ---
110
+ check "force push" "git push --force origin main" block
111
+ check "force push short flag" "git push origin main -f" block
112
+ check "--force-with-lease allowed" "git push --force-with-lease origin f" allow
113
+ check "push to main" "git push origin main" block
114
+ check "npm publish" "npm publish" block
115
+ check "writing .env" ".env" block Write
116
+ check ".env.example allowed" ".env.example" allow Write
117
+
118
+ # --- controls ---
119
+ check "ls" "ls -la" allow
120
+ check "git status" "git status" allow
121
+ check "npm test" "npm test" allow
122
+ check "echo" "echo hello" allow
123
+
124
+ echo
125
+ echo "plugins-word-order: $PASS passed, $FAIL failed"
126
+ [ "$FAIL" -eq 0 ]
@@ -0,0 +1,85 @@
1
+ #!/bin/bash
2
+ # Tests for powershell-remove-item-guard.sh
3
+ # Run: bash tests/powershell-remove-item-guard.test.sh
4
+ set -euo pipefail
5
+
6
+ PASS=0
7
+ FAIL=0
8
+ HOOK="$(dirname "$0")/../examples/powershell-remove-item-guard.sh"
9
+
10
+ # The verdict is the exit code, not the text. A refusal that only prints a word
11
+ # Claude Code does not act on is not a refusal: until 2026-09-19 this file checked
12
+ # for the string '"decision":"DENY"' in stdout, and passed all nine block cases
13
+ # while the guard refused none of them. One of the nine (C:\Users) was measured
14
+ # end to end against a do-nothing control; the other eight leave through the same
15
+ # two lines.
16
+ test_hook() {
17
+ local input="$1" expected="$2" desc="$3"
18
+ local out err exit_code=0
19
+ err=$(mktemp)
20
+ out=$(echo "$input" | bash "$HOOK" 2>"$err") || exit_code=$?
21
+ local stderr_text
22
+ stderr_text=$(cat "$err"); rm -f "$err"
23
+
24
+ if [ "$expected" = "DENY" ]; then
25
+ # exit 2 is what actually stops the tool call; the reason must reach stderr.
26
+ if [ "$exit_code" -eq 2 ] && echo "$stderr_text" | grep -q 'BLOCKED'; then
27
+ echo " PASS: $desc"
28
+ PASS=$((PASS + 1))
29
+ else
30
+ echo " FAIL: $desc (expected exit 2 + BLOCKED on stderr, got exit $exit_code, stdout: $out, stderr: $stderr_text)"
31
+ FAIL=$((FAIL + 1))
32
+ fi
33
+ elif [ "$expected" = "ASK" ]; then
34
+ if [ "$exit_code" -eq 0 ] && echo "$out" | grep -q '"permissionDecision":"ask"'; then
35
+ echo " PASS: $desc"
36
+ PASS=$((PASS + 1))
37
+ else
38
+ echo " FAIL: $desc (expected exit 0 + ask, got exit $exit_code, stdout: $out)"
39
+ FAIL=$((FAIL + 1))
40
+ fi
41
+ else
42
+ if [ "$exit_code" -eq 0 ] && ! echo "$out" | grep -q '"permissionDecision":"ask"'; then
43
+ echo " PASS: $desc"
44
+ PASS=$((PASS + 1))
45
+ else
46
+ echo " FAIL: $desc (expected exit 0 and no verdict, got exit $exit_code, stdout: $out)"
47
+ FAIL=$((FAIL + 1))
48
+ fi
49
+ fi
50
+ }
51
+
52
+ echo "powershell-remove-item-guard.sh tests"
53
+ echo ""
54
+
55
+ # --- Should DENY: system directory targets ---
56
+ test_hook '{"tool_input":{"command":"powershell -c \"Remove-Item -Recurse -Force C:\\Users\\john\""}}' DENY "Block Remove-Item on C:\\Users"
57
+ test_hook '{"tool_input":{"command":"powershell Remove-Item -Recurse /mnt/c/Windows"}}' DENY "Block Remove-Item on /mnt/c/Windows"
58
+ test_hook '{"tool_input":{"command":"Remove-Item -Recurse -Force \"C:\\Program Files\\app\""}}' DENY "Block Remove-Item on Program Files"
59
+
60
+ # --- Should DENY: node_modules junction traversal ---
61
+ test_hook '{"tool_input":{"command":"Remove-Item -Recurse -Force ./node_modules"}}' DENY "Block Remove-Item -Force on node_modules"
62
+ test_hook '{"tool_input":{"command":"Remove-Item -Recurse -Force .pnpm/store"}}' DENY "Block Remove-Item on .pnpm"
63
+ test_hook '{"tool_input":{"command":"Remove-Item -Recurse -Force worktree/packages"}}' DENY "Block Remove-Item on worktree"
64
+
65
+ # --- Should DENY: home directory ---
66
+ test_hook '{"tool_input":{"command":"Remove-Item -Recurse -Force $HOME/Documents"}}' DENY "Block Remove-Item on \$HOME"
67
+ test_hook '{"tool_input":{"command":"Remove-Item -Recurse $env:USERPROFILE"}}' DENY "Block Remove-Item on USERPROFILE"
68
+ test_hook '{"tool_input":{"command":"Remove-Item -Recurse -Force ~/projects"}}' DENY "Block Remove-Item on ~/"
69
+
70
+ # --- Should ASK: -Recurse -Force on an ordinary absolute data path (#64310) ---
71
+ test_hook '{"tool_input":{"command":"Remove-Item -Recurse -Force D:\\Clientes\\Yandy\\ENTREGABLES"}}' ASK "Confirm Remove-Item -Force on D:\\ client data (#64310)"
72
+ test_hook '{"tool_input":{"command":"Remove-Item -Force -Recurse E:\\work\\deliverables"}}' ASK "Confirm regardless of flag order on E:\\"
73
+ test_hook '{"tool_input":{"command":"Remove-Item -Recurse -Force \\\\nas\\share\\projects"}}' ASK "Confirm on UNC path"
74
+
75
+ # --- Should ALLOW: safe commands ---
76
+ test_hook '{"tool_input":{"command":"Remove-Item ./temp.txt"}}' ALLOW "Allow single file deletion"
77
+ test_hook '{"tool_input":{"command":"ls -la"}}' ALLOW "Allow non-Remove-Item command"
78
+ test_hook '{"tool_input":{"command":"rm -rf ./build"}}' ALLOW "Allow bash rm (different hook)"
79
+ test_hook '{"tool_input":{"command":"Get-ChildItem -Recurse"}}' ALLOW "Allow Get-ChildItem (read-only)"
80
+ test_hook '{"tool_input":{"command":"Remove-Item -Recurse -Force ./dist"}}' ALLOW "Allow relative force-delete (no absolute path)"
81
+ test_hook '{"tool_input":{"command":"Remove-Item -Recurse -Force .\\build\\out"}}' ALLOW "Allow relative Windows force-delete"
82
+
83
+ echo ""
84
+ echo "Results: $PASS passed, $FAIL failed"
85
+ [ "$FAIL" -eq 0 ] && exit 0 || exit 1