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,150 @@
1
+ #!/bin/bash
2
+ # ================================================================
3
+ # reroute-after-block-guard.sh — Stop "reroute after a block"
4
+ # ================================================================
5
+ # PURPOSE:
6
+ # PreToolUse hooks are stateless: each one evaluates the current
7
+ # action in isolation, with no memory that a sibling action was
8
+ # just denied. So a common failure trajectory slips through —
9
+ # a gate fires on an action, the agent substitutes an equivalent
10
+ # path toward the SAME target, and the next hook sees a fresh,
11
+ # individually-defensible action and lets it run.
12
+ # (anthropics/claude-code#70112: "Agent treats safety gates as
13
+ # obstacles to route around" — goal misgeneralization.)
14
+ #
15
+ # This hook adds the missing state. It reads the transcript: if
16
+ # the PREVIOUS tool call was blocked by a PreToolUse hook and the
17
+ # CURRENT action targets the same concrete FILE/path, it stops and
18
+ # surfaces to the human instead of letting the reroute proceed. A
19
+ # fired gate should RAISE the threshold for proceeding, not prompt
20
+ # a search for another path.
21
+ #
22
+ # This does not change the model's disposition; it converts a
23
+ # silent reroute into a hard stop for the case where the blast
24
+ # radius is concentrated on one target (a file, a path).
25
+ #
26
+ # Detects (only when ALL hold, else it stays out of the way):
27
+ # 1. the most recent tool result is an error, AND
28
+ # 2. its text is a Claude Code PreToolUse hook block
29
+ # (the "PreToolUse: ... hook error" runner phrasing), AND
30
+ # 3. the blocked action and the current action share a concrete
31
+ # filesystem path (anchored path or a path with a file
32
+ # extension). Bare word/word tokens and git refs (origin/main,
33
+ # refs/heads/...) are NOT treated as targets — inspecting a
34
+ # branch after a push is rejected must stay allowed.
35
+ #
36
+ # Does NOT block (fail-open by design — never guesses):
37
+ # - no transcript available / unreadable / jq missing
38
+ # - previous tool succeeded (no gate fired)
39
+ # - the error was a normal failure or a server-side rejection
40
+ # ("permission denied", git "blocked by required reviews", etc.)
41
+ # - no shared concrete file/path between blocked and current action
42
+ # - the human explicitly re-authorizes with CC_REROUTE_ALLOW=1
43
+ #
44
+ # Legitimate retry after fixing the real problem is expected: set
45
+ # CC_REROUTE_ALLOW=1 for that one command. Being forced to do so
46
+ # IS the point — it makes "proceed after a block" a conscious act.
47
+ #
48
+ # NOTE: this hook deliberately omits `set -e`/`pipefail`. Every
49
+ # jq/tail/grep failure must fall through to the next
50
+ # `[ -z "$VAR" ] && exit 0` guard; a crash exit (1) would be
51
+ # miscounted by Claude Code as a hook error rather than "allow".
52
+ #
53
+ # TRIGGER: PreToolUse MATCHER: "Bash|Edit|Write|MultiEdit"
54
+ #
55
+ # CONFIG:
56
+ # CC_REROUTE_ALLOW=1 one-shot override (proceed despite block)
57
+ # CC_REROUTE_DISABLE=1 disable this hook entirely
58
+ # ================================================================
59
+
60
+ [ "${CC_REROUTE_DISABLE:-0}" = "1" ] && exit 0
61
+ [ "${CC_REROUTE_ALLOW:-0}" = "1" ] && exit 0
62
+
63
+ command -v jq >/dev/null 2>&1 || exit 0
64
+
65
+ INPUT=$(cat)
66
+
67
+ TP=$(printf '%s' "$INPUT" | jq -r '.transcript_path // empty' 2>/dev/null)
68
+ [ -z "$TP" ] && exit 0
69
+ TP="${TP/#\~/$HOME}"
70
+ [ -r "$TP" ] || exit 0
71
+
72
+ # Current action's concrete target (command string or edited file).
73
+ CUR=$(printf '%s' "$INPUT" | jq -r '.tool_input.command // .tool_input.file_path // empty' 2>/dev/null)
74
+ [ -z "$CUR" ] && exit 0
75
+
76
+ # Only the tail matters: a blocked tool_use and its result are adjacent
77
+ # and most recent. Bound the work so the hook stays cheap.
78
+ WINDOW=$(tail -n 120 "$TP" 2>/dev/null)
79
+ [ -z "$WINDOW" ] && exit 0
80
+
81
+ # Most recent tool_result: {id, err, text}. Parse each line independently with
82
+ # `try fromjson catch empty` so one malformed line can't abort the scan and
83
+ # leave us reading a stale (older) result. content may be string or array.
84
+ LAST=$(printf '%s' "$WINDOW" \
85
+ | jq -Rc 'try (fromjson) catch empty
86
+ | select(.message.content? != null) | .message.content[]?
87
+ | select(.type=="tool_result")
88
+ | {id: .tool_use_id,
89
+ err: (.is_error // false),
90
+ text: (.content
91
+ | if type=="array" then (map(.text? // "") | join(" "))
92
+ elif type=="string" then .
93
+ else "" end)}' 2>/dev/null | tail -n 1)
94
+ [ -z "$LAST" ] && exit 0
95
+
96
+ ERR=$(printf '%s' "$LAST" | jq -r '.err // false' 2>/dev/null)
97
+ [ "$ERR" = "true" ] || exit 0
98
+
99
+ TEXT=$(printf '%s' "$LAST" | jq -r '.text // ""' 2>/dev/null)
100
+ # Was the previous action stopped by a Claude Code PreToolUse hook? Match ONLY
101
+ # the hook runner's own phrasing ("PreToolUse: <matcher> hook error"). Generic
102
+ # "permission denied" / git "blocked by ..." server rejections are NOT gates —
103
+ # matching them would false-block ordinary post-failure work.
104
+ printf '%s' "$TEXT" | grep -qE 'PreToolUse:[^|]*hook error' || exit 0
105
+
106
+ BLOCKED_ID=$(printf '%s' "$LAST" | jq -r '.id // empty' 2>/dev/null)
107
+ [ -z "$BLOCKED_ID" ] && exit 0
108
+
109
+ # The blocked action's concrete target, linked by tool_use_id.
110
+ BLOCKED=$(printf '%s' "$WINDOW" \
111
+ | jq -Rr --arg id "$BLOCKED_ID" 'try (fromjson) catch empty
112
+ | select(.message.content? != null) | .message.content[]?
113
+ | select(.type=="tool_use" and .id==$id)
114
+ | (.input.command // .input.file_path // empty)' 2>/dev/null | tail -n 1)
115
+ [ -z "$BLOCKED" ] && exit 0
116
+
117
+ # Shared concrete file/path? Pull slash-bearing tokens from the blocked action,
118
+ # keep only real filesystem paths (anchored with / ./ ../ ~/, or carrying a file
119
+ # extension), drop flags and git refs, and look for any in the current action.
120
+ # A file/path overlap is the strong, low-false-positive signal that the agent is
121
+ # rerouting toward the same resource rather than doing unrelated work.
122
+ SHARED=""
123
+ while IFS= read -r tok; do
124
+ [ -z "$tok" ] && continue
125
+ case "$tok" in
126
+ -*) continue ;; # flag
127
+ origin/*|upstream/*|remotes/*|refs/*|heads/*|tags/*) continue ;; # git refs
128
+ esac
129
+ [ "${#tok}" -lt 4 ] && continue
130
+ case "$tok" in
131
+ /*|./*|../*|~/*) : ;; # anchored filesystem path
132
+ *.*) : ;; # carries a file extension
133
+ *) continue ;; # bare word/word (e.g. origin/main) — not a target
134
+ esac
135
+ if printf '%s' "$CUR" | grep -qF -- "$tok"; then
136
+ SHARED="$tok"
137
+ break
138
+ fi
139
+ done < <(printf '%s' "$BLOCKED" | grep -oE '(/|\./|\.\./|~/)?[A-Za-z0-9_.-]+(/[A-Za-z0-9_.+-]+)+')
140
+
141
+ [ -z "$SHARED" ] && exit 0
142
+
143
+ cat >&2 <<MSG
144
+ ブロック: 直前の操作はゲート(PreToolUseのhook)で止められました。
145
+ 今回の操作は同じ対象「${SHARED}」へ向かう再ルートに見えます。
146
+ ゲートの発火は「別の経路を探せ」ではなく「立ち止まって正しさを確かめろ」の合図です。
147
+ 回避策を探さず、人へ状況を共有してください。
148
+ 本当に正しいと確認した上で進めるなら、その1コマンドだけ CC_REROUTE_ALLOW=1 を付けて実行してください。
149
+ MSG
150
+ exit 2
File without changes
@@ -0,0 +1,57 @@
1
+ #!/bin/bash
2
+ # resume-drift-watcher.sh — resume attachment relocation detector (Incident 2)
3
+ # Why: v2.1.69–v2.1.89 had a bug where --resume would relocate the original
4
+ # attachment payload out of messages[0] and into a later turn. The bug
5
+ # was marked fixed but residual drift still shows a tiny messages[0]
6
+ # (~350 bytes) when a resumed session is working correctly. A session
7
+ # with drifted attachments shows a very small messages[0] followed by
8
+ # disproportionately large messages[N] entries.
9
+ # Event: PostToolUse MATCHER: "*"
10
+ # Action: Per turn, record first-message byte length and total-message byte
11
+ # length to ~/.claude/logs/resume-drift.log. Compare manually: a
12
+ # session started with --resume whose messages[0] is much smaller
13
+ # than a fresh session's is a drift candidate.
14
+ #
15
+ # Review with:
16
+ # awk -F'\t' '$3<500 && $4>50000 {print}' ~/.claude/logs/resume-drift.log
17
+
18
+ set -u
19
+
20
+ LOG_DIR="${HOME}/.claude/logs"
21
+ LOG_FILE="${LOG_DIR}/resume-drift.log"
22
+ mkdir -p "$LOG_DIR" 2>/dev/null
23
+
24
+ INPUT=$(cat)
25
+
26
+ SESSION_ID=$(printf '%s' "$INPUT" | jq -r '.session_id // "unknown"' 2>/dev/null)
27
+ TRANSCRIPT=$(printf '%s' "$INPUT" | jq -r '.transcript_path // empty' 2>/dev/null)
28
+
29
+ if [ -z "$TRANSCRIPT" ] || [ ! -r "$TRANSCRIPT" ]; then
30
+ exit 0
31
+ fi
32
+
33
+ # First message — scan from top; stop at first user message.
34
+ FIRST_MSG=$(grep -m1 '"role":"user"' "$TRANSCRIPT" 2>/dev/null || true)
35
+ FIRST_LEN=$(printf '%s' "$FIRST_MSG" | wc -c | tr -d ' ')
36
+
37
+ # Total body size = file size of the transcript itself. This is a conservative
38
+ # proxy for request-body size: a resumed session with many large intermediate
39
+ # messages will have a large transcript.
40
+ TOTAL_LEN=$(wc -c < "$TRANSCRIPT" 2>/dev/null | tr -d ' ')
41
+ TOTAL_LEN="${TOTAL_LEN:-0}"
42
+
43
+ TURN_COUNT=$(grep -c '"role":' "$TRANSCRIPT" 2>/dev/null || echo 0)
44
+
45
+ TS=$(date -u +%Y-%m-%dT%H:%M:%SZ)
46
+ printf '%s\t%s\t%s\t%s\t%s\n' \
47
+ "$TS" "$SESSION_ID" "$FIRST_LEN" "$TOTAL_LEN" "$TURN_COUNT" \
48
+ >> "$LOG_FILE"
49
+
50
+ # Only emit a stderr warning after turn 2 (per Appendix B: "Only investigate
51
+ # after the first two turns of a resumed session"). Threshold: first-user
52
+ # message under 500 bytes while total already exceeds 50 KB = drift candidate.
53
+ if [ "$TURN_COUNT" -gt 4 ] && [ "$FIRST_LEN" -lt 500 ] && [ "$TOTAL_LEN" -gt 50000 ]; then
54
+ echo "⚠ resume-drift signal: messages[0]=${FIRST_LEN}B / total=${TOTAL_LEN}B (see #43278)" >&2
55
+ fi
56
+
57
+ exit 0
@@ -0,0 +1,125 @@
1
+ #!/bin/bash
2
+ # rg-replace-flag-detector.sh — Warn when Claude reaches for `rg -r` thinking it means recursive
3
+ #
4
+ # Solves: anthropics/claude-code#62016 — Claude's "grep -r" muscle memory leads it
5
+ # to invoke `rg -rn`, which ripgrep parses as `--replace=n`. Every match is
6
+ # silently rewritten to the literal `n` in stdout, exit 0, no error. Claude
7
+ # then reads its own corrupted output, misattributes the garbage to an
8
+ # "external cause" (post-processing layer, compression), and burns cycles
9
+ # debugging a self-inflicted flag bug.
10
+ #
11
+ # How it works: PreToolUse hook on Bash that scans the proposed command for the
12
+ # `rg -r[a-z]` pattern (and variants like `rg -rn`, `rg -rln`, `rg --replace`
13
+ # without TEXT). Emits a stderr advisory pointing to the correct flag
14
+ # (`-l` for line numbers is wrong too; line numbers are `-n`; recursive search
15
+ # is the default for ripgrep, so no `-r` needed at all). Default mode is
16
+ # advisory (exit 0 with stderr); strict mode (env var CC_RG_REPLACE_DETECTOR_MODE=strict)
17
+ # blocks the call (exit 2).
18
+ #
19
+ # This is the Cluster-4 hook from the 2026-05-25 customer pain audit
20
+ # (~/ops/customer-pain-audit-2026-05-25-post-launch-cluster.md). It catches
21
+ # the tool-flag self-deception pattern at the boundary where the corrupted
22
+ # output would otherwise enter the model's context.
23
+ #
24
+ # TRIGGER: PreToolUse
25
+ # MATCHER: "Bash"
26
+ #
27
+ # Usage:
28
+ # {
29
+ # "hooks": {
30
+ # "PreToolUse": [{
31
+ # "matcher": "Bash",
32
+ # "hooks": [{ "type": "command", "command": "~/.claude/hooks/rg-replace-flag-detector.sh" }]
33
+ # }]
34
+ # }
35
+ # }
36
+ #
37
+ # Configuration:
38
+ # CC_RG_REPLACE_DETECTOR_DISABLE=1 — skip the check entirely
39
+ # CC_RG_REPLACE_DETECTOR_MODE=strict — exit 2 (hard block) instead of exit 0 (advisory)
40
+
41
+ # Read stdin first so the upstream writer never sees EPIPE, even when disabled.
42
+ # Without jq, the parse below silently yields empty and this hook stops
43
+ # guarding - with no error anywhere. Say so. We deliberately do not exit
44
+ # here: blocking would halt every tool call, and exiting 0 would change
45
+ # the behaviour of guards that do not depend on the parsed value.
46
+ if ! command -v jq >/dev/null 2>&1; then
47
+ _nojq_warned="/tmp/cc-nojq-warned-rg-replace-flag-detector-$PPID"
48
+ [ -f "$_nojq_warned" ] || {
49
+ echo "WARNING [rg-replace-flag-detector]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
50
+ : > "$_nojq_warned"
51
+ }
52
+ fi
53
+
54
+ INPUT=$(cat 2>/dev/null || true)
55
+
56
+ [ "${CC_RG_REPLACE_DETECTOR_DISABLE:-0}" = "1" ] && exit 0
57
+ [ -z "$INPUT" ] && exit 0
58
+
59
+ # Only fire on Bash tool calls.
60
+ TOOL_NAME=$(printf '%s' "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
61
+ [ "$TOOL_NAME" = "Bash" ] || exit 0
62
+
63
+ COMMAND=$(printf '%s' "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
64
+ [ -z "$COMMAND" ] && exit 0
65
+
66
+ # Detect rg with -r or --replace flag.
67
+ # Patterns to catch:
68
+ # rg -r <TEXT>
69
+ # rg -rn / rg -rln (recursive + line numbers — but rg -r is --replace, not recursive)
70
+ # rg -r=<TEXT>
71
+ # rg --replace=<TEXT>
72
+ # rg --replace <TEXT>
73
+ # Patterns to skip (no false positive):
74
+ # rg -e <PATTERN> (extended regex, different flag)
75
+ # rg --regexp=<PATTERN>
76
+ # rg -i / --ignore-case
77
+ DETECTED=""
78
+
79
+ # Approach: confirm `rg` is invoked, then look for any short-flag token containing
80
+ # `r` anywhere in the rg invocation (separated by whitespace, not embedded in a
81
+ # long flag like `--regexp`).
82
+ #
83
+ # Step 1: confirm rg appears as a command (start of line, after pipe/semicolon,
84
+ # or after a word boundary like xargs).
85
+ if printf '%s' "$COMMAND" | grep -qE '(^|[[:space:]|;&]|xargs[[:space:]]+)rg([[:space:]]|$)'; then
86
+ # Step 2: look for any short-flag token (single -, not --) containing r.
87
+ # This matches `-r`, `-rn`, `-rln`, `-rH`, `-erR`, etc. but NOT `--regexp` or `--replace=X`.
88
+ if printf '%s' "$COMMAND" | grep -qE '(^|[[:space:]])-[a-zA-Z]*r[a-zA-Z]*([[:space:]]|$)'; then
89
+ DETECTED="short-flag"
90
+ fi
91
+ # Step 3: explicitly match --replace as a long flag.
92
+ if printf '%s' "$COMMAND" | grep -qE '(^|[[:space:]])--replace([=[:space:]]|$)'; then
93
+ DETECTED="long-flag"
94
+ fi
95
+ fi
96
+
97
+ [ -z "$DETECTED" ] && exit 0
98
+
99
+ cat >&2 <<EOF
100
+ <system-reminder>
101
+ rg-replace-flag-detector caught a likely flag-misuse pattern.
102
+
103
+ Command: $COMMAND
104
+
105
+ The flag \`-r\` in ripgrep means \`--replace=TEXT\`, NOT recursive. Recursive
106
+ search is the default for ripgrep. If you intended \`grep -rn\` muscle memory:
107
+
108
+ WRONG: rg -rn "pattern" path/ # rewrites every match to literal "n"
109
+ RIGHT: rg -n "pattern" path/ # line numbers, recursive by default
110
+ ALSO: rg "pattern" path/ # line numbers via default config
111
+ ALSO: rg --line-number "pattern" . # explicit long form
112
+
113
+ If you actually meant to replace text in output, ignore this warning. Otherwise
114
+ the resulting stdout is silently corrupted (exit 0, no error) and reading it
115
+ back will misattribute the garbage to an external cause.
116
+
117
+ Source: anthropics/claude-code#62016
118
+ EOF
119
+
120
+ # Strict mode blocks; default mode advises.
121
+ if [ "${CC_RG_REPLACE_DETECTOR_MODE:-advisory}" = "strict" ]; then
122
+ exit 2
123
+ fi
124
+
125
+ exit 0
@@ -0,0 +1,102 @@
1
+ #!/bin/bash
2
+ # rhetorical-verification-prompt-detector.sh — UserPromptSubmit hook
3
+ # Trigger: UserPromptSubmit
4
+ # Matcher: ""
5
+ #
6
+ # Solves: Issue #60107 — "the agent treated my question as rhetorical and
7
+ # confirmed". User asked a verification question; agent emitted an
8
+ # unconditional confirmation without running any verification step.
9
+ # User trusted the confirmation, deployed to production, and the
10
+ # deployed system crashed in full.
11
+ #
12
+ # Class of failure: claim-vs-reality divergence at the verification layer.
13
+ # The user's explicit verification intent ("is this really working?",
14
+ # "did this actually deploy?", "are you sure this is safe?") gets
15
+ # flattened by the model into a rhetorical-question reading, which
16
+ # the model then answers with social affirmation rather than with
17
+ # a tool-driven verification step.
18
+ #
19
+ # HOW IT WORKS:
20
+ # When the user submits a prompt containing verification-intent markers,
21
+ # the hook emits an additionalContext payload (via hookSpecificOutput)
22
+ # that explicitly tells the agent: this is a verification request, not
23
+ # a rhetorical one — do not respond with a bare affirmation; either run
24
+ # verification tool calls (Bash, Read, Grep) or state explicitly that
25
+ # verification was not performed.
26
+ #
27
+ # WHY THIS MATTERS:
28
+ # The 60107 failure shape is one of the cleanest examples of the broader
29
+ # pattern where the response surface asserts a claim that the runtime
30
+ # never verified. Most prevention efforts focus on the agent's *output*
31
+ # (caveat checkers, claim-vs-caveat validators). This hook addresses the
32
+ # *input* side: by labeling the user's prompt explicitly as a verification
33
+ # request before the agent processes it, the rhetorical-reading failure
34
+ # mode is harder to enter in the first place.
35
+ #
36
+ # TRIGGER: UserPromptSubmit
37
+ # MATCHER: ""
38
+ #
39
+ # CONFIGURATION:
40
+ # CC_RHETORICAL_VERIFY_DISABLE=1 disable the hook entirely
41
+ # CC_RHETORICAL_VERIFY_LOG=path append detection events (default off)
42
+ #
43
+ # SAFETY:
44
+ # - Read-only on the prompt; never modifies the user's input.
45
+ # - Emits advisory context via hookSpecificOutput; does not block the prompt.
46
+ # - The user's exact prompt still reaches the agent unchanged.
47
+ # - Exit 0 always; never blocks the session.
48
+ #
49
+ # REFERENCES:
50
+ # - anthropics/claude-code#60107 (2026-05-18, the canonical case)
51
+ # - https://gist.github.com/yurukusa/a5b2a32ca57e75eb1e96adcf67bcf2c3 (the
52
+ # nine-axis verification compilation, Axis 8 for self-acknowledged
53
+ # structural divergence)
54
+ set -euo pipefail
55
+
56
+ [ "${CC_RHETORICAL_VERIFY_DISABLE:-}" = "1" ] && exit 0
57
+
58
+ INPUT=$(cat)
59
+ PROMPT=$(echo "$INPUT" | jq -r '.prompt // empty' 2>/dev/null || true)
60
+ [ -z "$PROMPT" ] && exit 0
61
+
62
+ # Detection patterns — verification-intent markers.
63
+ # English and Japanese forms are both checked.
64
+ # These are conservative: only match phrases that strongly imply
65
+ # the user is asking for a *check*, not a *task*.
66
+ EN_PATTERNS='are you sure|are you certain|did (this|that|it) actually|did (this|that|it) really|did you (actually|really|verify|check|confirm)|can you (confirm|verify|double-?check|make sure)|is (this|that|it) (really|actually|definitely|truly) (working|correct|safe|done|deployed|complete|finished)|is (this|that|it) safe to|please (confirm|verify|double-?check|make sure)|just to (confirm|verify|be sure|double-?check)|double[ -]check|sanity check|are we (sure|certain|good)'
67
+
68
+ JA_PATTERNS='本当に|確かに|大丈夫(です)?(か|\?)|本当か|確認した|確認して(くれ|ください)|もう一度確認|再確認|間違いない(か|ですか|\?)?|本当だ?ね|チェックして|本当に(動いて|できて|終わって|成功して)|間違いなく'
69
+
70
+ MATCHED_MARKER=""
71
+
72
+ if echo "$PROMPT" | grep -qiE "$EN_PATTERNS"; then
73
+ MATCHED_MARKER=$(echo "$PROMPT" | grep -oiE "$EN_PATTERNS" | head -1)
74
+ elif echo "$PROMPT" | grep -qE "$JA_PATTERNS"; then
75
+ MATCHED_MARKER=$(echo "$PROMPT" | grep -oE "$JA_PATTERNS" | head -1)
76
+ fi
77
+
78
+ [ -z "$MATCHED_MARKER" ] && exit 0
79
+
80
+ # Optional logging
81
+ if [ -n "${CC_RHETORICAL_VERIFY_LOG:-}" ]; then
82
+ {
83
+ printf '[%s] rhetorical-verify-detected: marker=%q prompt_head=%q\n' \
84
+ "$(date -u +%Y-%m-%dT%H:%M:%SZ)" "$MATCHED_MARKER" "${PROMPT:0:200}"
85
+ } >> "$CC_RHETORICAL_VERIFY_LOG" 2>/dev/null || true
86
+ fi
87
+
88
+ # Emit additionalContext via hookSpecificOutput.
89
+ # Claude Code reads this as a system note to the agent.
90
+ ADDITIONAL_CONTEXT="Verification-intent detected in this user prompt (marker: \"${MATCHED_MARKER}\"). Treat this prompt as a verification request, NOT as a rhetorical question. Do not respond with a bare affirmation, social-confirmation phrase, or unverified \"yes\" / \"that's correct\" / \"all good\" / \"安心してください\". Instead: (1) run concrete verification tool calls (Bash, Read, Grep, file tests, status checks) appropriate to what is being verified; or (2) if verification is impossible in this context, state EXPLICITLY that verification was not performed and identify which check is missing. This guard exists because anthropics/claude-code#60107 documents a case where a verification question was read as rhetorical, an unverified confirmation was emitted, and the user's production system crashed in full as a direct consequence."
91
+
92
+ # Produce JSON output for hookSpecificOutput
93
+ jq -n \
94
+ --arg ctx "$ADDITIONAL_CONTEXT" \
95
+ '{
96
+ hookSpecificOutput: {
97
+ hookEventName: "UserPromptSubmit",
98
+ additionalContext: $ctx
99
+ }
100
+ }'
101
+
102
+ exit 0
File without changes
@@ -9,13 +9,18 @@
9
9
  # This hook blocks: ALL rm commands on important paths, even non-recursive
10
10
  #
11
11
  # What it blocks:
12
- # rm (any flags) on: /, ~, .., /home, /etc, /usr, /var, .git, .env
12
+ # rm (any flags) on: /, ~, .., /home, /Users, /etc, /usr, /var, .git, .env
13
+ # wildcard/glob rm reaching into a user/home/absolute path, e.g.
14
+ # rm -f ~/Downloads/*copy*.md (unpredictable match set — see #64559)
13
15
  # find -delete (any path)
16
+ # find ... | xargs rm without the null-delimited pair -print0 / xargs -0 (#69793 —
17
+ # a path with spaces splits into multiple targets and rm -rf wipes an unrelated dir)
14
18
  # shred (any file)
15
19
  # unlink on critical paths
16
20
  #
17
21
  # What it allows:
18
22
  # rm on safe targets: node_modules, dist, build, __pycache__, .cache, /tmp
23
+ # bare relative globs in the working dir: rm *.pyc, rm dist/*.js
19
24
  #
20
25
  # Usage: Add to settings.json as a PreToolUse hook
21
26
  #
@@ -33,18 +38,97 @@
33
38
  #
34
39
  # TRIGGER: PreToolUse MATCHER: "Bash"
35
40
 
41
+ # Without jq, the parse below silently yields empty and this hook stops
42
+ # guarding - with no error anywhere. Say so. We deliberately do not exit
43
+ # here: blocking would halt every tool call, and exiting 0 would change
44
+ # the behaviour of guards that do not depend on the parsed value.
45
+ if ! command -v jq >/dev/null 2>&1; then
46
+ _nojq_warned="/tmp/cc-nojq-warned-rm-safety-net-$PPID"
47
+ [ -f "$_nojq_warned" ] || {
48
+ echo "WARNING [rm-safety-net]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
49
+ : > "$_nojq_warned"
50
+ }
51
+ fi
52
+
36
53
  INPUT=$(cat)
37
54
  COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
38
55
 
56
+ # --- Look inside wrappers -----------------------------------------------------
57
+ # The rm analysis below opens only when the command *starts* with rm, and every
58
+ # other boundary in this file is a separator. A command inside a substitution,
59
+ # a subshell, or after a shell keyword is at neither, so it was never examined.
60
+ # Measured 2026-08-04: this hook blocked the bare deletion and passed all six
61
+ # wrappings of it. Claude Code 2.1.221 fixed the same shape in its own
62
+ # permission check ("hidden commands in [[ ]] regex conditionals").
63
+ #
64
+ # Replace the wrapping tokens with separators and run this same script once more
65
+ # against that text. Detection only: the rewritten text is never executed, and
66
+ # the message below keeps the command the user actually sent.
67
+ if [ -n "${CC_RMNET_UNWRAPPED:-}" ]; then
68
+ COMMAND="$CC_RMNET_UNWRAPPED"
69
+ elif [ -n "$COMMAND" ]; then
70
+ _rmnet_unwrapped=$(printf '%s' "$COMMAND" | sed -E \
71
+ -e 's/\$\(/ ; /g' -e 's/`/ ; /g' \
72
+ -e 's/(^|[[:space:]])\(/\1 ; /g' -e 's/\)([[:space:]]|$)/ ; \1/g' \
73
+ -e 's/(^|[[:space:]])(then|do|else|elif)([[:space:]])/\1 ; \3/g')
74
+ if [ "$_rmnet_unwrapped" != "$COMMAND" ]; then
75
+ CC_RMNET_UNWRAPPED="$_rmnet_unwrapped" bash "$0" </dev/null >/dev/null 2>&1
76
+ if [ "$?" = "2" ]; then
77
+ echo "BLOCKED: an rm on a critical path is hidden inside a wrapper." >&2
78
+ echo "Command: $COMMAND" >&2
79
+ echo "A substitution, a subshell or a shell keyword does not make it safe." >&2
80
+ exit 2
81
+ fi
82
+ fi
83
+ fi
84
+
39
85
  [ -z "$COMMAND" ] && exit 0
40
86
 
87
+ # The extractions in this hook used grep -oP, which is GNU-only. BSD grep
88
+ # (macOS) rejects -P, so the targets came back empty and every critical-path
89
+ # check silently found nothing to inspect. The GNU path is left exactly as it
90
+ # was; an equivalent runs where -P is absent. Defined at file scope because the
91
+ # find/xargs sections below use it too.
92
+ if echo x | grep -qP x 2>/dev/null; then HAS_PCRE=1; else HAS_PCRE=0; fi
93
+
94
+ # $1 = command word, $2 = operand pattern. \K has no POSIX equivalent, so the
95
+ # fallback matches from the command word and strips that prefix afterwards.
96
+ extract_operand() {
97
+ if [ "$HAS_PCRE" = 1 ]; then
98
+ grep -oP "$1\\s+\\K$2" 2>/dev/null || true
99
+ else
100
+ grep -oE "$1[[:space:]]+$2" 2>/dev/null | sed -E "s/^$1[[:space:]]+//" || true
101
+ fi
102
+ }
103
+
41
104
  # --- rm command analysis ---
42
- if echo "$COMMAND" | grep -qE '^\s*(sudo\s+)?rm\s'; then
105
+ # The gate used to be '^\s*(sudo\s+)?rm\s': the analysis opened only when the
106
+ # whole command began with rm, so `cd /tmp && rm -rf ~` never entered it.
107
+ # A separator in front is just as much a command start as the line start is.
108
+ if echo "$COMMAND" | grep -qE '(^|[;&|])[[:space:]]*(sudo[[:space:]]+)?rm[[:space:]]'; then
43
109
  # Safe targets that can be deleted freely
44
110
  SAFE_TARGETS="node_modules|dist|build|__pycache__|\.cache|\.pytest_cache|coverage|\.nyc_output|\.next|\.nuxt|tmp|temp"
111
+ CRITICAL="^/\$|^/home|^/Users|^/etc|^/usr|^/var|^/opt|^/root|^~|^\.\.|^\.git$|(^|/)\.env"
45
112
 
46
113
  # Extract the target (last argument after flags)
47
- TARGET=$(echo "$COMMAND" | grep -oP 'rm\s+[^;|&]*' | awk '{print $NF}')
114
+ if [ "$HAS_PCRE" = 1 ]; then
115
+ TARGET=$(echo "$COMMAND" | grep -oP 'rm\s+[^;|&]*' | awk '{print $NF}')
116
+ else
117
+ TARGET=$(echo "$COMMAND" | grep -oE 'rm[[:space:]]+[^;|&]*' | awk '{print $NF}')
118
+ fi
119
+
120
+ # Judge the target with its quotes removed. This hook blocks anything that
121
+ # is not on the safe list, so a quoted target used to be blocked whatever it
122
+ # was: `rm -rf "node_modules"` and `rm -rf "/"` failed the same test for the
123
+ # same reason -- the quote, not the path. Dropping the quote characters lets
124
+ # the safe list recognise the first and the critical list catch the second.
125
+ # Measured 2026-08-11: four ordinary quoted cleanups were blocked here.
126
+ # Messages keep $TARGET so the user sees what they actually typed.
127
+ #
128
+ # A name containing spaces (`rm -rf "my build dir"`) is still blocked. That
129
+ # is word splitting, not quoting, and fixing it means rewriting how operands
130
+ # are cut apart. Out of scope here; the tests record it as a known limit.
131
+ TARGET_UNQ=$(printf '%s' "$TARGET" | tr -d "\"'")
48
132
 
49
133
  # Block path traversal early
50
134
  if echo "$TARGET" | grep -qF '..'; then
@@ -52,6 +136,22 @@ if echo "$COMMAND" | grep -qE '^\s*(sudo\s+)?rm\s'; then
52
136
  exit 2
53
137
  fi
54
138
 
139
+ # Inspect EVERY non-flag argument for critical paths, not just the last one.
140
+ # The single-TARGET checks below use `awk '{print $NF}'` (last arg only), so
141
+ # "rm -rf /home/user/data node_modules" would early-exit on the safe LAST arg
142
+ # (node_modules) and never inspect the critical FIRST arg — a real bypass.
143
+ # set -f disables glob expansion of the split words (so "rm *.pyc" stays literal).
144
+ set -f
145
+ for arg in $(echo "$COMMAND" | extract_operand 'rm' '[^;|&]*'); do
146
+ case "$arg" in -*) continue ;; esac # skip flags
147
+ if printf '%s' "$arg" | tr -d "\"'" | grep -qE "$CRITICAL"; then
148
+ set +f
149
+ echo "BLOCKED: rm targeting critical path: $arg" >&2
150
+ exit 2
151
+ fi
152
+ done
153
+ set +f
154
+
55
155
  # Allow safe targets
56
156
  if echo "$TARGET" | grep -qE "^(\./)?(${SAFE_TARGETS})(/|$)"; then
57
157
  exit 0
@@ -62,9 +162,29 @@ if echo "$COMMAND" | grep -qE '^\s*(sudo\s+)?rm\s'; then
62
162
  exit 0
63
163
  fi
64
164
 
65
- # Block rm on critical paths
66
- CRITICAL="^/\$|^/home|^/etc|^/usr|^/var|^/opt|^/root|^~|^\.\.|^\.git$|^\.env"
67
- if echo "$TARGET" | grep -qE "$CRITICAL"; then
165
+ # Block wildcard/glob rm on absolute or home paths (#64559).
166
+ # A glob's match set can't be enumerated in advance, so a delete intended only
167
+ # for the model's own temp files (e.g. rm -f ~/Downloads/*copy*.md) can silently
168
+ # collateral-delete pre-existing user files whose names merely share the substring.
169
+ # Auto mode runs this with no confirmation. Bare relative globs (e.g. rm *.pyc in a
170
+ # project dir) are left alone; only globs reaching into a user/home/absolute path
171
+ # outside the safe-target list are gated, where the blast radius is unpredictable.
172
+ if echo "$TARGET" | grep -qE '[*?[]'; then
173
+ if echo "$TARGET" | grep -qE "^(/|~)"; then
174
+ echo "BLOCKED: wildcard rm on a user/absolute path — unpredictable match set: $TARGET" >&2
175
+ echo "A glob can delete pre-existing files you never named. List the matches first:" >&2
176
+ echo " ls -d $TARGET # confirm exactly what matches, then rm those names explicitly" >&2
177
+ exit 2
178
+ fi
179
+ fi
180
+
181
+ # Block rm on critical paths (/Users = macOS home, parity with /home on Linux)
182
+ # .env is matched at the start OR after any path segment, so a nested path
183
+ # like backend/.env or src/.env is caught too (#65034 — Claude deleted a
184
+ # .env living in a subdirectory, which the start-anchored pattern missed).
185
+ # CRITICAL is defined once near the top of this block (also used by the
186
+ # multi-argument loop above). This single-TARGET check stays as a backstop.
187
+ if echo "$TARGET_UNQ" | grep -qE "$CRITICAL"; then
68
188
  echo "BLOCKED: rm targeting critical path: $TARGET" >&2
69
189
  exit 2
70
190
  fi
@@ -72,7 +192,7 @@ if echo "$COMMAND" | grep -qE '^\s*(sudo\s+)?rm\s'; then
72
192
  # Block rm -rf on any non-safe path (extra safety)
73
193
  if echo "$COMMAND" | grep -qE 'rm\s+.*-[rRf]*[rR][rRf]*'; then
74
194
  # rm -rf on non-safe, non-tmp target — block unless it's a known safe directory
75
- if ! echo "$TARGET" | grep -qE "^(\./)?(${SAFE_TARGETS})(/|$)|^/tmp/"; then
195
+ if ! echo "$TARGET_UNQ" | grep -qE "^(\./)?(${SAFE_TARGETS})(/|$)|^/tmp/"; then
76
196
  echo "BLOCKED: rm -rf on non-safe target: $TARGET" >&2
77
197
  exit 2
78
198
  fi
@@ -82,7 +202,7 @@ fi
82
202
  # --- find -delete ---
83
203
  if echo "$COMMAND" | grep -qE 'find\s.*-delete'; then
84
204
  # Allow find in safe directories only
85
- FIND_PATH=$(echo "$COMMAND" | grep -oP 'find\s+\K[^\s]+')
205
+ FIND_PATH=$(echo "$COMMAND" | extract_operand 'find' '[^[:space:]]+')
86
206
  if echo "$FIND_PATH" | grep -qE '^\.|^node_modules|^dist|^build|^/tmp'; then
87
207
  exit 0
88
208
  fi
@@ -90,6 +210,29 @@ if echo "$COMMAND" | grep -qE 'find\s.*-delete'; then
90
210
  exit 2
91
211
  fi
92
212
 
213
+ # --- find | xargs rm without a null delimiter (#69793) ---
214
+ # find prints newline-separated paths; xargs WITHOUT -0 splits on ANY whitespace.
215
+ # So a single path containing spaces, e.g. "./Google Photos/a.jpg", is split into
216
+ # two arguments: "./Google" and "Photos/a.jpg". With rm -rf, the first token can
217
+ # match an UNRELATED real directory ("./Google") and wipe it whole — the reporter
218
+ # in #69793 lost ~28,800 files this way. The rm checks above can't catch this:
219
+ # the delete targets are produced by find at runtime, so there is no literal path
220
+ # in the command string to inspect. The only safe form is the null-delimited pair
221
+ # find -print0 | xargs -0 (or avoid xargs: find -delete / -exec rm {} +).
222
+ if echo "$COMMAND" | grep -qE 'xargs\b[^|]*\b(rm|rmdir|unlink|shred|trash|trash-put)\b'; then
223
+ # Require BOTH halves of the null-delimited pair: find's -print0 and xargs's -0.
224
+ if ! echo "$COMMAND" | grep -qE '\-print0' \
225
+ || ! echo "$COMMAND" | grep -qE 'xargs\s+[^|]*(-0|--null)'; then
226
+ echo "BLOCKED: 'xargs rm' without a null delimiter — paths with spaces split into multiple targets (#69793)." >&2
227
+ echo " A path like './Google Photos/a.jpg' splits into './Google' and 'Photos/a.jpg';" >&2
228
+ echo " rm -rf may then wipe an unrelated real directory. Use one of:" >&2
229
+ echo " find ... -delete" >&2
230
+ echo " find ... -exec rm -rf {} +" >&2
231
+ echo " find ... -print0 | xargs -0 rm -rf" >&2
232
+ exit 2
233
+ fi
234
+ fi
235
+
93
236
  # --- shred ---
94
237
  if echo "$COMMAND" | grep -qE '^\s*(sudo\s+)?shred\s'; then
95
238
  echo "BLOCKED: shred command (secure file deletion)" >&2