cc-safe-setup 29.8.0 → 30.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +72 -19
- package/.claude-plugin/plugin.json +1 -1
- package/CONTRIBUTING.md +7 -2
- package/COOKBOOK.md +50 -46
- package/LICENSE +21 -0
- package/MIGRATION.md +8 -8
- package/README.md +419 -512
- package/SAFETY_CHECKLIST.md +15 -7
- package/SERVICES.md +194 -0
- package/SETTINGS_REFERENCE.md +236 -17
- package/SKILL.md +5 -5
- package/TROUBLESHOOTING.md +35 -14
- package/action.yml +12 -4
- package/audit/README.md +84 -0
- package/audit/audit-checklist.md +152 -0
- package/audit/boundary-selftest.sh +85 -0
- package/audit/boundary.sh +123 -0
- package/audit/count-hooks.py +42 -0
- package/audit/find-dead-hooks.sh +82 -0
- package/audit/find-unfirable-rules.sh +142 -0
- package/audit/fire.sh +97 -0
- package/audit/selftest.sh +42 -0
- package/audit/unfirable-selftest.sh +81 -0
- package/audit-web/index.html +9 -9
- package/examples/README.md +54 -17
- package/examples/account-billing-log.sh +98 -0
- package/examples/account-routing-preflight.sh +123 -0
- package/examples/agent-sdk-credit-pool-monitor.sh +145 -0
- package/examples/agent-view-quota-decrement.sh +32 -0
- package/examples/agent-view-quota-warn.sh +94 -0
- package/examples/agents-md-edit-drift-warner.sh +223 -0
- package/examples/agents-md-loader.sh +160 -0
- package/examples/agents-md-sync-checker.sh +102 -0
- package/examples/ai-slop-punctuation-arrest.sh +210 -0
- package/examples/allowlist.sh +70 -10
- package/examples/always-allow-pattern-suggester.sh +125 -0
- package/examples/ansible-vault-guard.sh +2 -1
- package/examples/anthropic-base-url-guard.sh +76 -0
- package/examples/api-busyloop-guard.sh +123 -0
- package/examples/api-endpoint-guard.sh +12 -0
- package/examples/api-key-in-url-guard.sh +17 -1
- package/examples/api-rate-limit-guard.sh +36 -1
- package/examples/api-rate-limit-tracker.sh +12 -0
- package/examples/articulated-scope-capture.sh +101 -0
- package/examples/askuserquestion-autonomy-gate.sh +102 -0
- package/examples/attachment-traversal-guard.sh +118 -0
- package/examples/aup-block-pattern-logger.sh +161 -0
- package/examples/aup-false-positive-helper.sh +124 -0
- package/examples/aup-large-tool-output-warner.sh +282 -0
- package/examples/aup-retry-loop-guard.sh +229 -0
- package/examples/auth-expiry-reminder.sh +157 -0
- package/examples/auth-macos-sleep-detector.sh +185 -0
- package/examples/auth-path-detector.sh +171 -0
- package/examples/auth-status-checker.sh +157 -0
- package/examples/authorized-reconfirmation-detector.sh +195 -0
- package/examples/auto-approve-build.sh +39 -0
- package/examples/auto-approve-cargo.sh +31 -1
- package/examples/auto-approve-docker.sh +35 -0
- package/examples/auto-approve-git-read.sh +37 -14
- package/examples/auto-approve-go.sh +30 -1
- package/examples/auto-approve-gradle.sh +29 -1
- package/examples/auto-approve-make.sh +29 -1
- package/examples/auto-approve-maven.sh +29 -1
- package/examples/auto-approve-python.sh +41 -1
- package/examples/auto-approve-readonly-tools.sh +1 -0
- package/examples/auto-approve-readonly.sh +110 -33
- package/examples/auto-approve-ssh.sh +30 -1
- package/examples/auto-approve-test.sh +44 -0
- package/examples/auto-checkpoint.sh +1 -1
- package/examples/auto-compact-prep.sh +0 -0
- package/examples/auto-git-checkpoint.sh +0 -0
- package/examples/auto-mode-safe-commands.sh +53 -1
- package/examples/auto-mode-safety-enforcer.sh +151 -4
- package/examples/auto-push-session-branch.sh +22 -0
- package/examples/aws-production-guard.sh +13 -1
- package/examples/aws-region-guard.sh +1 -1
- package/examples/background-cost-launch-guard.sh +82 -0
- package/examples/background-task-guard.sh +12 -0
- package/examples/backup-before-refactor.sh +0 -0
- package/examples/banned-command-guard.sh +12 -0
- package/examples/bash-allowlist-secondary-check.sh +157 -0
- package/examples/bash-domain-allowlist.sh +12 -0
- package/examples/bash-fanout-bounded-rewriter.sh +191 -0
- package/examples/bash-heuristic-approver.sh +112 -10
- package/examples/bash-project-fence.sh +194 -0
- package/examples/bash-safety-auto-deny.sh +12 -0
- package/examples/bash-secret-output-detector.sh +44 -3
- package/examples/bash-trace-guard.sh +12 -0
- package/examples/bashrc-safety-check.sh +0 -0
- package/examples/bg-permission-prompt-warner.sh +182 -0
- package/examples/bg-task-cooldown-guard.sh +12 -0
- package/examples/binary-read-detector.sh +135 -0
- package/examples/binary-upload-guard.sh +12 -0
- package/examples/block-database-wipe.sh +35 -10
- package/examples/branch-name-check.sh +8 -3
- package/examples/branch-naming-convention.sh +0 -0
- package/examples/broad-find-guard.sh +12 -0
- package/examples/broad-prefix-session-trap-warner.sh +106 -0
- package/examples/bulk-file-delete-guard.sh +45 -0
- package/examples/bypass-mode-effective-verifier.sh +203 -0
- package/examples/cache-creation-drift-detector.sh +120 -0
- package/examples/cache-residue-detector.sh +195 -0
- package/examples/cache-tier-logger.sh +70 -0
- package/examples/cache-ttl-eviction-detector.sh +149 -0
- package/examples/cargo-publish-guard.sh +14 -1
- package/examples/case-insensitive-path-guard.sh +21 -2
- package/examples/case-sensitive-guard.sh +23 -2
- package/examples/cch-cache-guard.sh +0 -0
- package/examples/cch-sentinel-precommit-guard.sh +47 -0
- package/examples/check-abort-controller.sh +1 -1
- package/examples/check-accessibility.sh +0 -0
- package/examples/check-aria-labels.sh +0 -0
- package/examples/check-before-act-enforcer.sh +12 -0
- package/examples/check-charset-meta.sh +0 -0
- package/examples/check-cookie-flags.sh +0 -0
- package/examples/check-cors-config.sh +0 -0
- package/examples/check-csp-headers.sh +0 -0
- package/examples/check-csrf-protection.sh +0 -0
- package/examples/check-debounce.sh +1 -1
- package/examples/check-dependency-age.sh +0 -0
- package/examples/check-dependency-license.sh +0 -0
- package/examples/check-dockerfile-best-practice.sh +0 -0
- package/examples/check-error-boundaries.sh +0 -0
- package/examples/check-error-class.sh +1 -1
- package/examples/check-error-handling.sh +0 -0
- package/examples/check-error-logging.sh +1 -1
- package/examples/check-error-message.sh +0 -0
- package/examples/check-error-stack.sh +0 -0
- package/examples/check-favicon.sh +0 -0
- package/examples/check-git-hooks-compat.sh +0 -0
- package/examples/check-gitattributes.sh +0 -0
- package/examples/check-https-redirect.sh +0 -0
- package/examples/check-input-validation.sh +0 -0
- package/examples/check-lang-attribute.sh +0 -0
- package/examples/check-npm-scripts-exist.sh +0 -0
- package/examples/check-package-size.sh +0 -0
- package/examples/check-port-availability.sh +0 -0
- package/examples/check-promise-all.sh +1 -1
- package/examples/check-rate-limiting.sh +0 -0
- package/examples/check-return-types.sh +0 -0
- package/examples/check-semantic-versioning.sh +0 -0
- package/examples/check-suspense-fallback.sh +1 -1
- package/examples/check-test-exists.sh +0 -0
- package/examples/check-test-naming.sh +0 -0
- package/examples/check-timeout-cleanup.sh +1 -1
- package/examples/check-tls-version.sh +0 -0
- package/examples/check-unsubscribe.sh +1 -1
- package/examples/check-viewport-meta.sh +0 -0
- package/examples/check-worker-terminate.sh +1 -1
- package/examples/checkpoint-tamper-guard.sh +12 -0
- package/examples/chmod-guard.sh +12 -0
- package/examples/chown-guard.sh +24 -0
- package/examples/ci-workflow-guard.sh +6 -1
- package/examples/claim-verify-detector.sh +109 -0
- package/examples/claim-vs-caveat-checker.sh +77 -0
- package/examples/classifier-fallback-allow.sh +114 -40
- package/examples/claude-cache-gc.sh +1 -0
- package/examples/claude-code-version-pin-advisor.sh +183 -0
- package/examples/claude-md-reinjector.sh +129 -0
- package/examples/claude-md-size-monitor.sh +66 -0
- package/examples/claude-update-budget-guard.sh +123 -0
- package/examples/claude-update-smart.sh +113 -0
- package/examples/claudeignore-enforce-guard.sh +12 -0
- package/examples/claudemd-enforcer.sh +0 -0
- package/examples/claudemd-tool-prohibition.sh +128 -0
- package/examples/clear-command-confirm-guard.sh +32 -15
- package/examples/cli-config-pinning-detector.sh +162 -0
- package/examples/cliff-countdown-advisor.sh +96 -0
- package/examples/clipboard-secret-guard.sh +12 -0
- package/examples/closure-word-verify-gate.sh +150 -0
- package/examples/cloud-cli-guard.sh +39 -2
- package/examples/commit-all-scope-guard.sh +44 -0
- package/examples/commit-message-check.sh +1 -1
- package/examples/commit-message-quality.sh +6 -1
- package/examples/commitment-carry-forward-arrest.sh +361 -0
- package/examples/compact-alert-notification.sh +0 -0
- package/examples/compact-dispatch-watchdog.sh +149 -0
- package/examples/completion-claim-without-verification-detector.sh +207 -0
- package/examples/composer-guard.sh +12 -0
- package/examples/compound-bash-permission-resolver.sh +156 -0
- package/examples/compound-command-allow.sh +1 -1
- package/examples/compound-command-deny-enforcer.sh +183 -0
- package/examples/compound-inject-guard.sh +12 -0
- package/examples/concurrent-edit-lock.sh +12 -0
- package/examples/conflict-marker-guard.sh +12 -0
- package/examples/consecutive-error-breaker.sh +0 -0
- package/examples/console-log-count.sh +1 -0
- package/examples/context-compact-advisor.sh +29 -2
- package/examples/context-length-budget.sh +69 -0
- package/examples/context-threshold-alert.sh +12 -0
- package/examples/context-usage-drift-alert.sh +41 -13
- package/examples/conversation-history-guard.sh +12 -0
- package/examples/core-file-protect-guard.sh +12 -0
- package/examples/cors-star-warn.sh +0 -0
- package/examples/cost-incident-self-audit.sh +162 -0
- package/examples/cowork-claude-md-load-checker.sh +100 -0
- package/examples/cowork-fuse-staleness-watcher.sh +140 -0
- package/examples/cowork-hook-absence-warner.sh +167 -0
- package/examples/cowork-model-picker-advisor.sh +115 -0
- package/examples/credential-exfil-guard.sh +65 -4
- package/examples/credential-file-cat-guard.sh +17 -1
- package/examples/cron-create-receipt.sh +112 -0
- package/examples/cron-modification-guard.sh +12 -0
- package/examples/cross-product-mcp-spawn-detector.sh +178 -0
- package/examples/cwd-project-boundary-guard.sh +0 -0
- package/examples/daemon-zombie-worker-surfacer.sh +118 -0
- package/examples/daily-cost-guard.sh +164 -0
- package/examples/daily-usage-tracker.sh +0 -0
- package/examples/dangerous-pip-flag-guard.sh +12 -0
- package/examples/db-connect-guard.sh +13 -1
- package/examples/denied-action-retry-guard.sh +12 -0
- package/examples/deny-bypass-detector.sh +12 -0
- package/examples/deny-rule-integrity-verifier.sh +181 -0
- package/examples/dependency-install-guard.sh +12 -0
- package/examples/deploy-guard.sh +14 -2
- package/examples/deploy-path-verify-guard.sh +12 -0
- package/examples/deployment-readback-gate.sh +135 -0
- package/examples/deployment-readback-gh-adapter.sh +247 -0
- package/examples/deployment-verify-guard.sh +25 -2
- package/examples/destructive-db-script-write-guard.sh +166 -0
- package/examples/destructive-migration-write-guard.sh +163 -0
- package/examples/diff-size-guard.sh +12 -0
- package/examples/disabled-feature-toggle-advisor.sh +88 -0
- package/examples/disk-partition-guard.sh +12 -0
- package/examples/dispatch-allowlist-preflight.sh +301 -0
- package/examples/dispatch-liveness-watchdog.sh +216 -0
- package/examples/dispatch-receipt.sh +174 -0
- package/examples/django-migrate-guard.sh +12 -0
- package/examples/dns-config-guard.sh +12 -0
- package/examples/docker-dangerous-guard.sh +12 -0
- package/examples/docker-volume-guard.sh +0 -0
- package/examples/dockerfile-latest-guard.sh +1 -0
- package/examples/dotenv-anthropic-key-billing-guard.sh +99 -0
- package/examples/dotenv-commit-guard.sh +12 -0
- package/examples/dotenv-read-guard.sh +12 -0
- package/examples/dotfile-protection-guard.sh +12 -0
- package/examples/dotnet-build-on-edit.sh +1 -1
- package/examples/drizzle-migrate-guard.sh +27 -2
- package/examples/echo-probe-spam-detector.sh +176 -0
- package/examples/edit-counter-test-gate.sh +12 -0
- package/examples/edit-error-counter.sh +1 -1
- package/examples/edit-guard.sh +12 -0
- package/examples/edit-old-string-validator.sh +12 -0
- package/examples/edit-quote-ambiguity-guard.sh +97 -0
- package/examples/edit-retry-loop-guard.sh +0 -0
- package/examples/edit-verify.sh +0 -0
- package/examples/env-inline-secret-guard.sh +14 -2
- package/examples/env-naming-convention.sh +0 -0
- package/examples/env-prod-guard.sh +0 -0
- package/examples/env-required-check.sh +0 -0
- package/examples/env-source-guard.sh +12 -0
- package/examples/env-var-check.sh +24 -1
- package/examples/ephemeral-container-detector.sh +147 -0
- package/examples/error-memory-guard.sh +12 -0
- package/examples/evidence-claim-gate.sh +187 -0
- package/examples/exploration-budget-guard.sh +12 -0
- package/examples/expo-eject-guard.sh +13 -0
- package/examples/extended-thinking-loop-guard.sh +139 -0
- package/examples/extended-thinking-resume-warning.sh +119 -0
- package/examples/extended-thinking-tool-use-mismatch-detector.sh +212 -0
- package/examples/fabricated-command-detector.sh +145 -0
- package/examples/false-disk-full-guard.sh +63 -0
- package/examples/feature-deprecation-detector.sh +109 -0
- package/examples/file-change-tracker.sh +1 -1
- package/examples/file-change-undo-tracker.sh +0 -0
- package/examples/file-edit-backup.sh +63 -14
- package/examples/file-reference-check.sh +0 -0
- package/examples/file-size-limit.sh +12 -0
- package/examples/financial-operation-guard.sh +12 -0
- package/examples/firewall-guard.sh +12 -0
- package/examples/fish-shell-wrapper.sh +125 -7
- package/examples/five-hundred-milestone.sh +1 -0
- package/examples/flask-static-route-guard.sh +89 -0
- package/examples/forbidden-response-phrase-detector.sh +161 -0
- package/examples/gem-push-guard.sh +13 -0
- package/examples/gh-cli-destructive-guard.sh +13 -1
- package/examples/git-checkout-safety-guard.sh +12 -0
- package/examples/git-checkout-uncommitted-guard.sh +12 -0
- package/examples/git-config-guard.sh +12 -0
- package/examples/git-crypt-worktree-guard.sh +12 -0
- package/examples/git-filter-repo-guard.sh +56 -0
- package/examples/git-history-rewrite-guard.sh +12 -0
- package/examples/git-hook-bypass-guard.sh +0 -0
- package/examples/git-maintenance-guard.sh +83 -0
- package/examples/git-merge-conflict-prevent.sh +0 -0
- package/examples/git-message-length-check.sh +0 -0
- package/examples/git-message-length.sh +0 -0
- package/examples/git-operations-require-approval.sh +68 -14
- package/examples/git-pack-temp-cleanup-guard.sh +102 -0
- package/examples/git-push-blast-radius-guard.sh +218 -0
- package/examples/git-remote-guard.sh +24 -3
- package/examples/git-rm-orphan-wipe-guard.sh +85 -0
- package/examples/git-stash-before-checkout.sh +12 -0
- package/examples/git-stash-before-danger.sh +0 -0
- package/examples/git-submodule-guard.sh +69 -2
- package/examples/git-tag-guard.sh +12 -0
- package/examples/github-actions-secret-guard.sh +0 -0
- package/examples/gitignore-check.sh +0 -0
- package/examples/gitops-drift-guard.sh +12 -0
- package/examples/go-mod-tidy-warn.sh +1 -0
- package/examples/go-vet-after-edit.sh +12 -0
- package/examples/goal-iteration-limit-warner.sh +152 -0
- package/examples/grep-nul-false-negative-guard.sh +30 -0
- package/examples/growthbook-flag-monitor.sh +257 -0
- package/examples/hallucination-url-check.sh +1 -1
- package/examples/halt-signal-detector.sh +135 -0
- package/examples/handoff-on-clear.sh +65 -0
- package/examples/hardcoded-ip-guard.sh +1 -0
- package/examples/headless-empty-result-guard.sh +0 -0
- package/examples/headless-stop-guard.sh +0 -0
- package/examples/helm-install-guard.sh +2 -1
- package/examples/home-critical-bash-guard.sh +17 -1
- package/examples/hook-debug-wrapper.sh +6 -2
- package/examples/hook-permission-fixer.sh +0 -0
- package/examples/hook-self-disable-detector.sh +99 -0
- package/examples/hook-stdout-sanitizer.sh +6 -2
- package/examples/hook-tamper-guard.sh +12 -0
- package/examples/idle-session-cost-alert.sh +0 -0
- package/examples/image-dimension-guard.sh +109 -0
- package/examples/image-file-validator.sh +0 -0
- package/examples/iteration-quality-degradation-detector.sh +170 -0
- package/examples/java-compile-on-edit.sh +1 -1
- package/examples/json-syntax-check.sh +0 -0
- package/examples/k8s-production-guard.sh +13 -1
- package/examples/kill-process-guard.sh +12 -0
- package/examples/kubernetes-guard.sh +13 -1
- package/examples/laravel-artisan-guard.sh +13 -0
- package/examples/large-file-guard.sh +1 -1
- package/examples/log-level-guard.sh +0 -0
- package/examples/log-truncation-guard.sh +12 -0
- package/examples/long-session-malformed-tool-call-detector.sh +183 -0
- package/examples/loop-detector.sh +12 -0
- package/examples/magic-number-warn.sh +1 -0
- package/examples/main-branch-warn.sh +12 -0
- package/examples/markdown-link-check.sh +0 -0
- package/examples/max-concurrent-agents.sh +12 -0
- package/examples/max-edit-size-guard.sh +13 -0
- package/examples/max-file-count-guard.sh +0 -0
- package/examples/max-file-delete-count.sh +0 -0
- package/examples/max-function-length.sh +1 -0
- package/examples/max-import-count.sh +0 -0
- package/examples/max-subagent-count.sh +0 -0
- package/examples/mcp-config-freeze.sh +12 -0
- package/examples/mcp-config-poisoning-audit.sh +150 -0
- package/examples/mcp-data-boundary.sh +1 -1
- package/examples/mcp-misdiagnosis-arrest.sh +209 -0
- package/examples/mcp-orphan-leak-warner.sh +49 -0
- package/examples/mcp-permissions-ask-warner.sh +151 -0
- package/examples/mcp-routine-approval-detector.sh +154 -0
- package/examples/mcp-server-allowlist.sh +12 -0
- package/examples/mcp-server-guard.sh +12 -0
- package/examples/mcp-startup-bloat-detector.sh +87 -0
- package/examples/mcp-stdio-compatibility-test.sh +153 -0
- package/examples/mcp-tool-audit-log.sh +0 -0
- package/examples/mcp-tool-guard.sh +101 -1
- package/examples/mcp-warmup-wait.sh +0 -0
- package/examples/memory-chain-audit.sh +56 -0
- package/examples/memory-orphan-detector.sh +188 -0
- package/examples/memory-write-guard.sh +99 -17
- package/examples/migration-verify-guard.sh +12 -0
- package/examples/model-swap-suggester.sh +177 -0
- package/examples/model-version-alert.sh +5 -1
- package/examples/model-version-lock.sh +63 -0
- package/examples/move-delete-sequence-guard.sh +33 -2
- package/examples/multi-file-plan-routing-gate.sh +192 -0
- package/examples/multi-vendor-concurrent-warner.sh +108 -0
- package/examples/multi-window-auth-drift-detector.sh +183 -0
- package/examples/multiline-command-approver.sh +161 -23
- package/examples/nested-background-agent-guard.sh +109 -0
- package/examples/nested-spawn-inflight-guard.sh +178 -0
- package/examples/network-exfil-guard.sh +12 -0
- package/examples/network-guard.sh +12 -0
- package/examples/network-interface-guard.sh +12 -0
- package/examples/nextjs-env-guard.sh +1 -1
- package/examples/no-absolute-import.sh +0 -0
- package/examples/no-alert-confirm-prompt.sh +0 -0
- package/examples/no-anonymous-default-export.sh +0 -0
- package/examples/no-any-type.sh +0 -0
- package/examples/no-any-typescript.sh +1 -0
- package/examples/no-ask-human.sh +12 -0
- package/examples/no-assignment-in-condition.sh +0 -0
- package/examples/no-base64-exfil.sh +12 -0
- package/examples/no-callback-hell.sh +0 -0
- package/examples/no-circular-dependency.sh +0 -0
- package/examples/no-cleartext-storage.sh +0 -0
- package/examples/no-commented-code.sh +0 -0
- package/examples/no-commit-fixup.sh +0 -0
- package/examples/no-console-assert.sh +0 -0
- package/examples/no-console-error-swallow.sh +0 -0
- package/examples/no-console-in-prod.sh +0 -0
- package/examples/no-console-log-commit.sh +12 -0
- package/examples/no-console-log.sh +0 -0
- package/examples/no-console-time.sh +0 -0
- package/examples/no-cors-wildcard.sh +4 -1
- package/examples/no-curl-upload.sh +0 -0
- package/examples/no-dangerouslySetInnerHTML.sh +0 -0
- package/examples/no-dangling-await.sh +1 -0
- package/examples/no-debug-commit.sh +12 -0
- package/examples/no-debug-in-commit.sh +0 -0
- package/examples/no-deep-nesting.sh +0 -0
- package/examples/no-deep-relative-import.sh +1 -0
- package/examples/no-default-credentials.sh +0 -0
- package/examples/no-deploy-friday.sh +13 -1
- package/examples/no-disabled-test.sh +0 -0
- package/examples/no-document-write.sh +0 -0
- package/examples/no-empty-function.sh +0 -0
- package/examples/no-eval-in-template.sh +0 -0
- package/examples/no-eval-template.sh +3 -1
- package/examples/no-eval.sh +0 -0
- package/examples/no-exec-user-input.sh +0 -0
- package/examples/no-fixme-ship.sh +12 -0
- package/examples/no-floating-promises.sh +0 -0
- package/examples/no-force-flag.sh +22 -5
- package/examples/no-force-install.sh +0 -0
- package/examples/no-git-amend.sh +12 -0
- package/examples/no-git-rebase-public.sh +0 -0
- package/examples/no-global-install.sh +12 -0
- package/examples/no-global-state.sh +0 -0
- package/examples/no-hardcoded-port.sh +1 -0
- package/examples/no-hardcoded-url.sh +0 -0
- package/examples/no-helmet-missing.sh +0 -0
- package/examples/no-http-url.sh +1 -0
- package/examples/no-http-without-https.sh +0 -0
- package/examples/no-inline-style.sh +0 -0
- package/examples/no-inline-styles.sh +1 -0
- package/examples/no-innerhtml.sh +0 -0
- package/examples/no-install-global.sh +12 -0
- package/examples/no-jwt-in-url.sh +0 -0
- package/examples/no-large-commit.sh +0 -0
- package/examples/no-localhost-expose.sh +0 -0
- package/examples/no-magic-number.sh +0 -0
- package/examples/no-md5-sha1.sh +0 -0
- package/examples/no-mixed-line-endings.sh +8 -1
- package/examples/no-mutation-in-reducer.sh +0 -0
- package/examples/no-nested-ternary.sh +0 -0
- package/examples/no-network-exfil.sh +0 -0
- package/examples/no-open-redirect.sh +0 -0
- package/examples/no-output-truncation.sh +12 -0
- package/examples/no-package-downgrade.sh +0 -0
- package/examples/no-package-lock-edit.sh +12 -0
- package/examples/no-path-join-user-input.sh +0 -0
- package/examples/no-port-bind.sh +0 -0
- package/examples/no-process-exit.sh +0 -0
- package/examples/no-prototype-pollution.sh +0 -0
- package/examples/no-push-without-ci.sh +0 -0
- package/examples/no-push-without-tests.sh +12 -0
- package/examples/no-raw-password-in-url.sh +0 -0
- package/examples/no-root-user-docker.sh +1 -0
- package/examples/no-root-write.sh +12 -0
- package/examples/no-secrets-in-args.sh +4 -1
- package/examples/no-secrets-in-logs.sh +0 -0
- package/examples/no-sensitive-log.sh +0 -0
- package/examples/no-sleep-in-hooks.sh +0 -0
- package/examples/no-star-import-python.sh +1 -0
- package/examples/no-string-concat-sql.sh +0 -0
- package/examples/no-sudo-guard.sh +12 -0
- package/examples/no-sync-fs.sh +0 -0
- package/examples/no-todo-in-merge.sh +0 -0
- package/examples/no-todo-in-production.sh +1 -0
- package/examples/no-todo-without-issue.sh +0 -0
- package/examples/no-unused-import.sh +0 -0
- package/examples/no-var-keyword.sh +0 -0
- package/examples/no-verify-blocker.sh +12 -0
- package/examples/no-wget-piped-bash.sh +12 -0
- package/examples/no-wildcard-cors.sh +0 -0
- package/examples/no-wildcard-delete.sh +0 -0
- package/examples/no-wildcard-import.sh +0 -0
- package/examples/no-with-statement.sh +0 -0
- package/examples/no-write-outside-src.sh +0 -0
- package/examples/no-xml-external-entity.sh +0 -0
- package/examples/non-english-quality-warner.sh +156 -0
- package/examples/notify-waiting.sh +1 -1
- package/examples/npm-audit-warn.sh +0 -0
- package/examples/npm-global-install-guard.sh +12 -0
- package/examples/npm-publish-guard.sh +12 -0
- package/examples/npm-script-injection.sh +0 -0
- package/examples/npm-supply-chain-guard.sh +0 -0
- package/examples/nuxt-config-guard.sh +1 -0
- package/examples/oauth-refresh-monitor.sh +210 -0
- package/examples/opus-degradation-tracker.sh +187 -0
- package/examples/opus48-routine-task-warning.sh +196 -0
- package/examples/opus48-thinking-wedge-advisor.sh +143 -0
- package/examples/output-credential-scan.sh +1 -1
- package/examples/output-secret-mask.sh +31 -9
- package/examples/output-token-spike-detector.sh +145 -0
- package/examples/package-json-guard.sh +12 -0
- package/examples/package-lock-frozen.sh +12 -0
- package/examples/parallel-batch-size-limiter.sh +121 -0
- package/examples/parallel-cascade-detector.sh +116 -0
- package/examples/partial-view-claim-arrest.sh +174 -0
- package/examples/path-deny-bash-guard.sh +12 -0
- package/examples/path-traversal-guard.sh +12 -0
- package/examples/per-prompt-token-cap.sh +124 -0
- package/examples/permission-audit-log.sh +1 -1
- package/examples/permission-denial-enforcer.sh +12 -0
- package/examples/permission-entry-validator.sh +0 -0
- package/examples/persisted-1m-model-advisor.sh +88 -0
- package/examples/php-lint-on-edit.sh +1 -1
- package/examples/pii-upload-guard.sh +12 -0
- package/examples/pip-publish-guard.sh +13 -0
- package/examples/pip-requirements-guard.sh +12 -0
- package/examples/pip-venv-required.sh +12 -0
- package/examples/plan-mode-edit-guard.sh +12 -0
- package/examples/plan-mode-enforcer.sh +12 -0
- package/examples/plan-mode-strict-guard.sh +12 -0
- package/examples/plugin-hooks-json-bloat-detector.sh +169 -0
- package/examples/plugin-process-cleanup.sh +0 -0
- package/examples/polyglot-rm-guard.sh +12 -0
- package/examples/post-compact-safety.sh +12 -0
- package/examples/post-edit-disk-verify.sh +152 -0
- package/examples/powershell-remove-item-guard.sh +85 -0
- package/examples/pr-description-check.sh +0 -0
- package/examples/pr-duplicate-guard.sh +13 -0
- package/examples/pre-bash-sed-line-ending-windows.sh +87 -0
- package/examples/pre-compact-knowledge-save.sh +0 -0
- package/examples/pre-compact-transcript-backup.sh +0 -0
- package/examples/pre-execution-claim-detector.sh +179 -0
- package/examples/prefer-builtin-tools.sh +10 -1
- package/examples/prefer-const.sh +0 -0
- package/examples/prefer-dedicated-tools.sh +12 -0
- package/examples/prefer-optional-chaining.sh +0 -0
- package/examples/prisma-migrate-guard.sh +24 -7
- package/examples/production-port-kill-guard.sh +12 -0
- package/examples/prompt-injection-guard.sh +2 -1
- package/examples/prompt-usage-logger.sh +0 -0
- package/examples/protect-claudemd.sh +12 -0
- package/examples/protect-dotfiles.sh +12 -0
- package/examples/proxy-capture-suggester.sh +159 -0
- package/examples/public-artefact-socratic-narrowing.sh +232 -0
- package/examples/public-repo-push-guard.sh +12 -0
- package/examples/push-requires-test-pass-record.sh +0 -0
- package/examples/push-requires-test-pass.sh +12 -0
- package/examples/quota-anomaly-detector.sh +173 -0
- package/examples/quota-reset-audit.sh +58 -0
- package/examples/quoted-flag-approver.sh +99 -10
- package/examples/rails-migration-guard.sh +12 -0
- package/examples/rate-limit-guard.sh +0 -0
- package/examples/read-all-files-enforcer.sh +0 -0
- package/examples/read-budget-guard.sh +12 -0
- package/examples/read-loop-detector.sh +59 -0
- package/examples/read-once-guard.sh +96 -0
- package/examples/read-only-mode.sh +12 -0
- package/examples/readme-exists-check.sh +0 -0
- package/examples/record-read-coverage.sh +73 -0
- package/examples/redirect-fragment-warner.sh +149 -0
- package/examples/redis-flushall-guard.sh +13 -0
- package/examples/redundant-read-blocker.sh +132 -0
- package/examples/refusal-arrest-gate.sh +248 -0
- package/examples/registry-publish-guard.sh +13 -1
- package/examples/remote-control-billing-classifier.sh +135 -0
- package/examples/replace-all-guard.sh +12 -0
- package/examples/repo-visibility-guard.sh +12 -0
- package/examples/reroute-after-block-guard.sh +150 -0
- package/examples/response-budget-guard.sh +0 -0
- package/examples/resume-drift-watcher.sh +57 -0
- package/examples/rg-replace-flag-detector.sh +125 -0
- package/examples/rhetorical-verification-prompt-detector.sh +102 -0
- package/examples/ripgrep-permission-fix.sh +0 -0
- package/examples/rm-safety-net.sh +151 -8
- package/examples/role-tool-guard.sh +12 -0
- package/examples/route-handler-emptiness-gate.sh +324 -0
- package/examples/ruby-lint-on-edit.sh +1 -1
- package/examples/runtime-binary-change-detector.sh +102 -0
- package/examples/same-command-repeat-detector.sh +196 -0
- package/examples/same-correction-arrest.sh +169 -0
- package/examples/sandbox-denywrite-enforcer.sh +78 -0
- package/examples/sandbox-relative-path-audit.sh +83 -25
- package/examples/sandbox-write-verify.sh +12 -0
- package/examples/schema-migration-guard.sh +0 -0
- package/examples/scope-expansion-receipt.sh +178 -0
- package/examples/scope-guard.sh +88 -9
- package/examples/secret-file-read-guard.sh +12 -0
- package/examples/secret-file-write-guard.sh +150 -0
- package/examples/self-modify-bypass-guard.sh +0 -0
- package/examples/sensitive-file-read-guard.sh +23 -3
- package/examples/sensitive-log-guard.sh +1 -0
- package/examples/server-side-prompt-injection-detector.sh +69 -0
- package/examples/session-agent-cost-limiter.sh +12 -0
- package/examples/session-backup-on-start.sh +1 -1
- package/examples/session-cost-alert.sh +12 -0
- package/examples/session-drift-guard.sh +12 -0
- package/examples/session-duration-guard.sh +25 -2
- package/examples/session-end-logger.sh +0 -0
- package/examples/session-health-monitor.sh +0 -0
- package/examples/session-index-repair.sh +1 -1
- package/examples/session-memory-watchdog.sh +1 -0
- package/examples/session-permission-reset-guard.sh +12 -0
- package/examples/session-persistence-verifier.sh +93 -0
- package/examples/session-plugin-pin-watch.sh +68 -0
- package/examples/session-rate-monitor.sh +176 -0
- package/examples/session-resume-env-fix.sh +0 -0
- package/examples/session-start-quota-status.sh +193 -0
- package/examples/session-start-safety-check.sh +55 -3
- package/examples/session-state-saver.sh +0 -0
- package/examples/session-summary-stop.sh +1 -1
- package/examples/session-summary.sh +0 -0
- package/examples/session-token-counter.sh +1 -1
- package/examples/settings-hooks-key-restorer.sh +99 -0
- package/examples/settings-json-health-check.sh +57 -0
- package/examples/settings-json-model-guard.sh +0 -0
- package/examples/settings-regression-tester.sh +188 -0
- package/examples/shell-config-truncation-guard.sh +12 -0
- package/examples/shell-wrapper-guard.sh +12 -0
- package/examples/skill-cumulative-size-detector.sh +104 -0
- package/examples/skill-description-drop-detector.sh +148 -0
- package/examples/skill-gate.sh +0 -0
- package/examples/skill-truncation-detector.sh +154 -0
- package/examples/skills-context-recorder.sh +167 -0
- package/examples/skills-load-verifier.sh +96 -0
- package/examples/skills-settings-validator.sh +139 -0
- package/examples/sonnet-45-deprecation-helper.sh +85 -0
- package/examples/spec-file-scope-guard.sh +12 -0
- package/examples/spring-profile-guard.sh +1 -0
- package/examples/spurious-malformed-notice-detector.sh +247 -0
- package/examples/sql-bulk-delete-warn.sh +88 -0
- package/examples/sql-injection-detect.sh +0 -0
- package/examples/ssh-key-protect.sh +12 -0
- package/examples/staged-secret-scan.sh +22 -1
- package/examples/stale-temp-settings-detector.sh +86 -0
- package/examples/standing-rule-session-surfacer.sh +137 -0
- package/examples/stop-hook-sigterm-wrapper.sh +182 -0
- package/examples/stop-transcript-write-health.sh +64 -0
- package/examples/strict-allowlist.sh +57 -15
- package/examples/strip-coauthored-by.sh +50 -10
- package/examples/subagent-blast-radius-guard.sh +184 -0
- package/examples/subagent-boundary-precheck.sh +126 -0
- package/examples/subagent-budget-guard.sh +12 -0
- package/examples/subagent-claudemd-inject.sh +0 -0
- package/examples/subagent-closure-verify-gate.sh +164 -0
- package/examples/subagent-destructive-git-guard.sh +120 -0
- package/examples/subagent-error-detector.sh +0 -0
- package/examples/subagent-forged-system-reminder-guard.sh +156 -0
- package/examples/subagent-identity-leak-guard.sh +102 -0
- package/examples/subagent-identity-reassertion.sh +51 -0
- package/examples/subagent-inheritance-tester.sh +179 -0
- package/examples/subagent-permission-mode-guard.sh +110 -0
- package/examples/subagent-scope-guard.sh +12 -0
- package/examples/subagent-spawn-verification-enforcer.sh +102 -0
- package/examples/subagent-tool-allowlist-enforcer.sh +101 -0
- package/examples/subagent-tool-call-limiter.sh +87 -15
- package/examples/subcommand-chain-guard.sh +12 -0
- package/examples/subscription-api-billing-warner.sh +160 -0
- package/examples/subscription-bypass-detector.sh +152 -0
- package/examples/svelte-lint-on-edit.sh +1 -0
- package/examples/swift-build-on-edit.sh +1 -1
- package/examples/symlink-guard.sh +27 -2
- package/examples/symlink-protect.sh +1 -0
- package/examples/system-dir-protection-guard.sh +73 -8
- package/examples/system-message-workaround.sh +38 -13
- package/examples/system-package-guard.sh +12 -0
- package/examples/systemd-service-guard.sh +12 -0
- package/examples/task-integrity-guard.sh +12 -0
- package/examples/temp-file-cleanup.sh +1 -1
- package/examples/temporal-suggestion-detector.sh +135 -0
- package/examples/terraform-guard.sh +27 -6
- package/examples/test-after-edit.sh +1 -1
- package/examples/test-before-push.sh +12 -0
- package/examples/test-coverage-reminder.sh +24 -1
- package/examples/thinking-budget-effort-mismatch-detector.sh +149 -0
- package/examples/timezone-guard.sh +0 -0
- package/examples/tmp-output-size-guard.sh +0 -0
- package/examples/todo-check.sh +1 -1
- package/examples/token-budget-guard.sh +12 -0
- package/examples/token-budget-per-task.sh +12 -0
- package/examples/token-usage-tracker.sh +7 -1
- package/examples/tokenizer-ratio-alert-corpus.sh +90 -0
- package/examples/tokenizer-ratio-alert.sh +104 -0
- package/examples/tool-call-rate-limiter.sh +0 -0
- package/examples/tool-result-correlation-checker.sh +167 -0
- package/examples/tool-result-size-guard.sh +132 -0
- package/examples/tool-retry-budget-guard.sh +12 -0
- package/examples/transcript-contamination-detector.sh +138 -0
- package/examples/trustfall-mcp-injection-guard.sh +103 -0
- package/examples/ultrareview-large-diff-advisor.sh +184 -0
- package/examples/unbounded-output-guard.sh +94 -0
- package/examples/uncommitted-changes-stop.sh +1 -0
- package/examples/uncommitted-discard-guard.sh +23 -5
- package/examples/uncommitted-work-guard.sh +12 -0
- package/examples/usage-warn.sh +0 -0
- package/examples/user-account-guard.sh +12 -0
- package/examples/userprompt-submit-receipt.sh +123 -0
- package/examples/variable-expansion-guard.sh +12 -0
- package/examples/verify-after-publish-reminder.sh +93 -0
- package/examples/verify-before-commit.sh +12 -0
- package/examples/version-bump-detector.sh +156 -0
- package/examples/version-regression-warner.sh +144 -0
- package/examples/vue-lint-on-edit.sh +1 -0
- package/examples/warn-cron-cost-trap.sh +173 -0
- package/examples/webfetch-runaway-guard.sh +89 -0
- package/examples/wellness-break-reminder.sh +118 -0
- package/examples/windows-destructive-command-guard.sh +177 -0
- package/examples/windows-path-guard.sh +12 -0
- package/examples/windows-python-stub-detector.sh +63 -0
- package/examples/work-hours-guard.sh +12 -0
- package/examples/working-directory-fence.sh +12 -0
- package/examples/workspace-lease-guard.sh +205 -0
- package/examples/worktree-create-log.sh +1 -0
- package/examples/worktree-delete-guard.sh +12 -0
- package/examples/worktree-edit-boundary-guard.sh +127 -0
- package/examples/worktree-escape-write-guard.sh +114 -0
- package/examples/worktree-hook-linker.sh +0 -0
- package/examples/worktree-hooks-path-fix.sh +111 -0
- package/examples/worktree-parent-write-guard.sh +43 -0
- package/examples/worktree-project-unify.sh +2 -1
- package/examples/worktree-remove-uncommitted-guard.sh +13 -0
- package/examples/worktree-unmerged-guard.sh +7 -1
- package/examples/write-byte-integrity-verifier.sh +190 -0
- package/examples/write-empty-content-guard.sh +67 -0
- package/examples/write-nul-corruption-detector.sh +61 -0
- package/examples/write-overwrite-confirm.sh +160 -14
- package/examples/write-secret-guard.sh +27 -5
- package/examples/write-shrink-guard.sh +12 -0
- package/examples/write-test-ratio.sh +0 -0
- package/examples/wsl-host-disk-space-guard.sh +97 -0
- package/examples/xml-format-leak-detector.sh +266 -0
- package/examples/yaml-syntax-check.sh +12 -0
- package/hooks/hooks.json +6 -6
- package/index.mjs +1699 -183
- package/mission.md +2 -0
- package/package.json +4 -4
- package/plugins/credential-guard/.claude-plugin/plugin.json +9 -7
- package/plugins/git-protection/.claude-plugin/plugin.json +10 -8
- package/plugins/safety-essentials/.claude-plugin/plugin.json +9 -7
- package/plugins/token-guard/.claude-plugin/plugin.json +10 -8
- package/scripts/agents-md-sync-setup.sh +156 -0
- package/scripts/autonomy-blocked-summary.sh +148 -0
- package/scripts/build-search-index.py +43 -0
- package/scripts/build-sitemap.py +119 -0
- package/scripts/cc-doctor.sh +192 -0
- package/scripts/check-hook-event-names.py +127 -0
- package/scripts/check-misfire-instrument.sh +64 -0
- package/scripts/claim-verify-audit.sh +467 -0
- package/scripts/cowork-claudemd-helper.sh +136 -0
- package/scripts/june-15-deprecated-model-scan.sh +111 -0
- package/scripts/measure-heredoc-shapes.sh +67 -0
- package/scripts/measure-literal-match-misfire.sh +110 -0
- package/scripts/probe-scope-guard-branches.sh +48 -0
- package/scripts/probe-skip-line-both-ways.sh +65 -0
- package/scripts/receipts-aggregate.py +199 -0
- package/scripts/session-forensic-audit.py +360 -0
- package/scripts.json +9 -9
- package/scripts.json.bak-2026-07-27-find +13 -0
- package/skills/safety-setup/SKILL.md +5 -5
- package/tests/approve-side-remaining-two.test.sh +129 -0
- package/tests/approver-list-granularity.test.sh +145 -0
- package/tests/askuserquestion-autonomy-gate.test.sh +181 -0
- package/tests/audit-ci-gate.test.sh +87 -0
- package/tests/audit-cross-layer-claudemd.test.sh +170 -0
- package/tests/audit-fail-open-parse.test.sh +100 -0
- package/tests/auto-approve-compound-tail.test.sh +194 -0
- package/tests/auto-mode-path-invoked-commands.test.sh +89 -0
- package/tests/auto-mode-quoted-targets.test.sh +127 -0
- package/tests/auto-mode-unquoted-targets.test.sh +112 -0
- package/tests/bash-secret-output-detector-detects.test.sh +102 -0
- package/tests/blindspots-cross-layer.test.sh +177 -0
- package/tests/block-database-wipe.test.sh +64 -0
- package/tests/bundled-short-flags-bypass.test.sh +85 -0
- package/tests/cd-git-allow-compound-tail.test.sh +67 -0
- package/tests/chown-guard-filesystem-root.test.sh +64 -0
- package/tests/ci-workflow-guard-skip-rule.test.sh +115 -0
- package/tests/compound-deny-safe-rm-targets.test.sh +105 -0
- package/tests/core-scripts-parser-fallback.test.sh +140 -0
- package/tests/destructive-guard-bare-glob.test.sh +74 -0
- package/tests/destructive-guard-every-operand.test.sh +100 -0
- package/tests/destructive-guard-find-deletion.test.sh +114 -0
- package/tests/destructive-guard-flag-order.test.sh +106 -0
- package/tests/destructive-guard-mentions-vs-invocations.test.sh +107 -0
- package/tests/destructive-guard-quoted-target.test.sh +89 -0
- package/tests/destructive-guard-separators.test.sh +105 -0
- package/tests/destructive-guard-variable-target.test.sh +98 -0
- package/tests/destructive-guard-wrapped-command.test.sh +91 -0
- package/tests/doctor-hook-disabling-env.test.sh +92 -0
- package/tests/doctor-misspelled-settings-keys.test.sh +106 -0
- package/tests/example-guards-wrapped-command.test.sh +169 -0
- package/tests/file-edit-backup.test.sh +93 -0
- package/tests/git-filter-repo-guard.test.sh +60 -0
- package/tests/git-global-options-bypass.test.sh +141 -0
- package/tests/git-invocation-prefixes-all-guards.test.sh +114 -0
- package/tests/git-maintenance-guard.test.sh +83 -0
- package/tests/git-pack-temp-cleanup-guard.test.sh +133 -0
- package/tests/git-rm-orphan-wipe-guard.test.sh +66 -0
- package/tests/git-submodule-guard.test.sh +50 -0
- package/tests/grep-pcre-portability.test.sh +155 -0
- package/tests/hook-registration-matches-input.test.sh +73 -0
- package/tests/hook-trigger-matches-envelope.test.sh +178 -0
- package/tests/install-does-not-claim-protection.test.sh +110 -0
- package/tests/install-example-standalone-tools.test.sh +139 -0
- package/tests/line-continuation-bypass.test.sh +114 -0
- package/tests/mcp-config-poisoning-audit.test.sh +106 -0
- package/tests/nested-background-agent-guard.test.sh +58 -0
- package/tests/no-unqualified-safety-claims.test.sh +114 -0
- package/tests/option-eating-grep-patterns.test.sh +130 -0
- package/tests/outdated-core-guards.test.sh +134 -0
- package/tests/outdated-report.test.sh +155 -0
- package/tests/output-secret-mask-warns.test.sh +73 -0
- package/tests/plugin-hooks-fail-open-under-sh.test.sh +165 -0
- package/tests/plugins-word-order.test.sh +126 -0
- package/tests/powershell-remove-item-guard.test.sh +85 -0
- package/tests/project-dir-naming.test.sh +103 -0
- package/tests/quoted-safe-targets-and-mentions.test.sh +190 -0
- package/tests/reroute-after-block-guard.test.sh +104 -0
- package/tests/secret-guard-documented-promises.test.sh +97 -0
- package/tests/session-plugin-pin-watch.test.sh +45 -0
- package/tests/settings-unreadable-refuses-to-write.test.sh +95 -0
- package/tests/shield-no-silent-adoption.test.py +110 -0
- package/tests/shield-no-silent-adoption.test.sh +46 -0
- package/tests/stop-transcript-write-health.test.sh +46 -0
- package/tests/system-dir-guard-root-erased.test.sh +66 -0
- package/tests/test-account-billing-log.sh +100 -0
- package/tests/test-account-routing-preflight.sh +77 -0
- package/tests/test-agent-sdk-credit-pool-monitor.sh +157 -0
- package/tests/test-agent-view-quota-warn.sh +184 -0
- package/tests/test-agents-md-edit-drift-warner.sh +176 -0
- package/tests/test-agents-md-loader.sh +204 -0
- package/tests/test-agents-md-sync-checker.sh +125 -0
- package/tests/test-ai-slop-punctuation-arrest.sh +280 -0
- package/tests/test-allowlist.sh +60 -0
- package/tests/test-always-allow-pattern-suggester.sh +147 -0
- package/tests/test-anthropic-base-url-guard.sh +88 -0
- package/tests/test-articulated-scope-capture.sh +139 -0
- package/tests/test-attachment-traversal-guard.sh +168 -0
- package/tests/test-aup-block-pattern-logger.sh +315 -0
- package/tests/test-aup-false-positive-helper.sh +188 -0
- package/tests/test-aup-large-tool-output-warner.sh +370 -0
- package/tests/test-aup-retry-loop-guard.sh +341 -0
- package/tests/test-auth-expiry-reminder.sh +303 -0
- package/tests/test-auth-macos-sleep-detector.sh +254 -0
- package/tests/test-auth-path-detector.sh +232 -0
- package/tests/test-auth-status-checker.sh +233 -0
- package/tests/test-authorized-reconfirmation-detector.sh +280 -0
- package/tests/test-background-cost-launch-guard.sh +62 -0
- package/tests/test-bash-allowlist-secondary-check.sh +143 -0
- package/tests/test-bash-fanout-bounded-rewriter.sh +186 -0
- package/tests/test-bash-project-fence.sh +127 -0
- package/tests/test-bg-permission-prompt-warner.sh +221 -0
- package/tests/test-binary-read-detector.sh +173 -0
- package/tests/test-broad-prefix-session-trap-warner.sh +167 -0
- package/tests/test-bulk-delete-target-resolution.sh +49 -0
- package/tests/test-bypass-mode-effective-verifier.sh +179 -0
- package/tests/test-cache-creation-drift-detector.sh +244 -0
- package/tests/test-cache-residue-detector.sh +429 -0
- package/tests/test-cache-tier-logger.sh +59 -0
- package/tests/test-cache-ttl-eviction-detector.sh +282 -0
- package/tests/test-cch-sentinel-precommit-guard.sh +64 -0
- package/tests/test-claim-verify-detector.sh +222 -0
- package/tests/test-claim-vs-caveat-checker.sh +134 -0
- package/tests/test-claude-code-version-pin-advisor.sh +353 -0
- package/tests/test-claude-md-reinjector.sh +173 -0
- package/tests/test-claude-md-size-monitor.sh +107 -0
- package/tests/test-claude-update-budget-guard.sh +132 -0
- package/tests/test-claude-update-smart.sh +91 -0
- package/tests/test-claudemd-tool-prohibition.sh +239 -0
- package/tests/test-cli-config-pinning-detector.sh +233 -0
- package/tests/test-cliff-countdown-advisor.sh +138 -0
- package/tests/test-closure-word-verify-gate.sh +158 -0
- package/tests/test-commit-all-scope-guard.sh +73 -0
- package/tests/test-commitment-carry-forward-arrest.sh +250 -0
- package/tests/test-compact-dispatch-watchdog.sh +147 -0
- package/tests/test-completion-claim-without-verification-detector.sh +326 -0
- package/tests/test-compound-bash-permission-resolver.sh +264 -0
- package/tests/test-compound-command-deny-enforcer.sh +67 -0
- package/tests/test-context-length-budget.sh +68 -0
- package/tests/test-context-usage-drift-alert.sh +52 -22
- package/tests/test-cost-incident-self-audit.sh +94 -0
- package/tests/test-cowork-claude-md-load-checker.sh +257 -0
- package/tests/test-cowork-claudemd-helper.sh +141 -0
- package/tests/test-cowork-fuse-staleness-watcher.sh +287 -0
- package/tests/test-cowork-hook-absence-warner.sh +230 -0
- package/tests/test-cowork-model-picker-advisor.sh +317 -0
- package/tests/test-credential-exfil-guard.sh +62 -0
- package/tests/test-cron-create-receipt.sh +165 -0
- package/tests/test-cross-product-mcp-spawn-detector.sh +112 -0
- package/tests/test-daemon-zombie-worker-surfacer.sh +71 -0
- package/tests/test-daily-cost-guard.sh +131 -0
- package/tests/test-deny-rule-integrity-verifier.sh +288 -0
- package/tests/test-deployment-readback-gate.sh +92 -0
- package/tests/test-deployment-readback-gh-adapter.sh +163 -0
- package/tests/test-disabled-feature-toggle-advisor.sh +78 -0
- package/tests/test-dispatch-allowlist-preflight.sh +385 -0
- package/tests/test-dispatch-liveness-watchdog.sh +319 -0
- package/tests/test-dispatch-receipt.sh +314 -0
- package/tests/test-dotenv-anthropic-key-billing-guard.sh +160 -0
- package/tests/test-echo-probe-spam-detector.sh +143 -0
- package/tests/test-edit-quote-ambiguity-guard.sh +75 -0
- package/tests/test-ephemeral-container-detector.sh +251 -0
- package/tests/test-evidence-claim-gate.sh +291 -0
- package/tests/test-extended-thinking-loop-guard.sh +289 -0
- package/tests/test-extended-thinking-resume-warning.sh +240 -0
- package/tests/test-extended-thinking-tool-use-mismatch-detector.sh +236 -0
- package/tests/test-fabricated-command-detector.sh +296 -0
- package/tests/test-false-disk-full-guard.sh +36 -0
- package/tests/test-feature-deprecation-detector.sh +117 -0
- package/tests/test-forbidden-response-phrase-detector.sh +246 -0
- package/tests/test-git-operations-require-approval.sh +53 -0
- package/tests/test-git-push-blast-radius-guard.sh +115 -0
- package/tests/test-goal-iteration-limit-warner.sh +128 -0
- package/tests/test-growthbook-flag-monitor.sh +428 -0
- package/tests/test-halt-signal-detector.sh +120 -0
- package/tests/test-hook-self-disable-detector.sh +232 -0
- package/tests/test-iteration-quality-degradation-detector.sh +244 -0
- package/tests/test-long-session-malformed-tool-call-detector.sh +185 -0
- package/tests/test-marketplace-plugins.sh +193 -0
- package/tests/test-mcp-misdiagnosis-arrest.sh +235 -0
- package/tests/test-mcp-orphan-leak-warner.sh +71 -0
- package/tests/test-mcp-permissions-ask-warner.sh +207 -0
- package/tests/test-mcp-routine-approval-detector.sh +229 -0
- package/tests/test-mcp-startup-bloat-detector.sh +141 -0
- package/tests/test-mcp-stdio-compatibility-test.sh +112 -0
- package/tests/test-memory-chain-audit.sh +59 -0
- package/tests/test-memory-orphan-detector.sh +227 -0
- package/tests/test-model-swap-suggester.sh +368 -0
- package/tests/test-model-version-lock.sh +83 -0
- package/tests/test-multi-file-plan-routing-gate.sh +277 -0
- package/tests/test-multi-window-auth-drift-detector.sh +262 -0
- package/tests/test-nested-spawn-inflight-guard.sh +281 -0
- package/tests/test-no-force-flag.sh +49 -0
- package/tests/test-non-english-quality-warner.sh +229 -0
- package/tests/test-oauth-refresh-monitor.sh +311 -0
- package/tests/test-opus-degradation-tracker.sh +274 -0
- package/tests/test-opus48-routine-task-warning.sh +201 -0
- package/tests/test-opus48-thinking-wedge-advisor.sh +249 -0
- package/tests/test-output-token-spike-detector.sh +315 -0
- package/tests/test-parallel-batch-size-limiter.sh +228 -0
- package/tests/test-parallel-cascade-detector.sh +191 -0
- package/tests/test-partial-view-claim-arrest.sh +272 -0
- package/tests/test-per-prompt-token-cap.sh +136 -0
- package/tests/test-persisted-1m-model-advisor.sh +71 -0
- package/tests/test-plugin-hooks-json-bloat-detector.sh +267 -0
- package/tests/test-post-edit-disk-verify.sh +294 -0
- package/tests/test-pre-bash-sed-line-ending-windows.sh +108 -0
- package/tests/test-pre-execution-claim-detector.sh +366 -0
- package/tests/test-private-key-backup-and-git-credentials.sh +100 -0
- package/tests/test-proxy-capture-suggester.sh +214 -0
- package/tests/test-public-artefact-socratic-narrowing.sh +346 -0
- package/tests/test-quota-anomaly-detector.sh +321 -0
- package/tests/test-quota-reset-audit.sh +81 -0
- package/tests/test-read-loop-detector.sh +137 -0
- package/tests/test-read-once-guard.sh +85 -0
- package/tests/test-receipts-aggregate.sh +143 -0
- package/tests/test-redirect-fragment-warner.sh +130 -0
- package/tests/test-redundant-read-blocker.sh +155 -0
- package/tests/test-refusal-arrest-gate.sh +303 -0
- package/tests/test-remote-control-billing-classifier.sh +125 -0
- package/tests/test-resume-drift-watcher.sh +65 -0
- package/tests/test-rg-replace-flag-detector.sh +175 -0
- package/tests/test-rhetorical-verification-prompt-detector.sh +237 -0
- package/tests/test-rm-safety-net.sh +115 -0
- package/tests/test-route-handler-emptiness-gate.sh +300 -0
- package/tests/test-runtime-binary-change-detector.sh +196 -0
- package/tests/test-same-command-repeat-detector.sh +165 -0
- package/tests/test-same-correction-arrest.sh +165 -0
- package/tests/test-scope-expansion-receipt.sh +207 -0
- package/tests/test-server-side-prompt-injection-detector.sh +181 -0
- package/tests/test-session-persistence-verifier.sh +128 -0
- package/tests/test-session-rate-monitor.sh +284 -0
- package/tests/test-session-start-quota-status.sh +210 -0
- package/tests/test-session-start-safety-check.sh +138 -0
- package/tests/test-settings-hooks-key-restorer.sh +257 -0
- package/tests/test-settings-json-health-check.sh +70 -0
- package/tests/test-settings-regression-tester.sh +197 -0
- package/tests/test-skill-cumulative-size-detector.sh +198 -0
- package/tests/test-skill-description-drop-detector.sh +236 -0
- package/tests/test-skill-truncation-detector.sh +263 -0
- package/tests/test-skills-context-recorder.sh +329 -0
- package/tests/test-skills-load-verifier.sh +184 -0
- package/tests/test-skills-settings-validator.sh +242 -0
- package/tests/test-sonnet-45-deprecation-helper.sh +150 -0
- package/tests/test-spurious-malformed-notice-detector.sh +290 -0
- package/tests/test-sql-bulk-delete-warn.sh +123 -0
- package/tests/test-ssh-key-protect.sh +81 -0
- package/tests/test-stale-temp-settings-detector.sh +161 -0
- package/tests/test-standing-rule-session-surfacer.sh +215 -0
- package/tests/test-starter-hooks-manifest.sh +96 -0
- package/tests/test-stop-hook-sigterm-wrapper.sh +258 -0
- package/tests/test-strict-allowlist.sh +72 -0
- package/tests/test-subagent-boundary-precheck.sh +137 -0
- package/tests/test-subagent-closure-verify-gate.sh +193 -0
- package/tests/test-subagent-destructive-git-guard.sh +86 -0
- package/tests/test-subagent-identity-leak-guard.sh +62 -0
- package/tests/test-subagent-identity-reassertion.sh +61 -0
- package/tests/test-subagent-inheritance-tester.sh +319 -0
- package/tests/test-subagent-permission-mode-guard.sh +61 -0
- package/tests/test-subagent-spawn-verification-enforcer.sh +60 -0
- package/tests/test-subagent-tool-allowlist-enforcer.sh +62 -0
- package/tests/test-subagent-tool-call-limiter.sh +97 -0
- package/tests/test-subscription-api-billing-warner.sh +138 -0
- package/tests/test-subscription-bypass-detector.sh +255 -0
- package/tests/test-temporal-suggestion-detector.sh +183 -0
- package/tests/test-thinking-budget-effort-mismatch-detector.sh +327 -0
- package/tests/test-tokenizer-ratio-alert-corpus.sh +77 -0
- package/tests/test-tokenizer-ratio-alert.sh +93 -0
- package/tests/test-tool-result-correlation-checker.sh +264 -0
- package/tests/test-tool-result-size-guard.sh +121 -0
- package/tests/test-transcript-contamination-detector.sh +264 -0
- package/tests/test-trigger-header-parsing.sh +151 -0
- package/tests/test-ultrareview-large-diff-advisor.sh +192 -0
- package/tests/test-userprompt-submit-receipt.sh +181 -0
- package/tests/test-verify-after-publish-reminder.sh +184 -0
- package/tests/test-version-bump-detector.sh +212 -0
- package/tests/test-version-regression-warner.sh +165 -0
- package/tests/test-warn-cron-cost-trap.sh +82 -0
- package/tests/test-webfetch-runaway-guard.sh +77 -0
- package/tests/test-wellness-break-reminder.sh +138 -0
- package/tests/test-windows-destructive-command-guard.sh +169 -0
- package/tests/test-windows-python-stub-detector.sh +146 -0
- package/tests/test-worktree-edit-boundary-guard.sh +219 -0
- package/tests/test-write-byte-integrity-verifier.sh +192 -0
- package/tests/test-xml-format-leak-detector.sh +299 -0
- package/tests/trustfall-mcp-injection-guard.test.sh +183 -0
- package/tests/workspace-lease-guard.test.sh +144 -0
- package/tests/worktree-escape-write-guard.test.sh +68 -0
- package/tests/worktree-hooks-path-fix.test.sh +181 -0
- package/tests/worktree-parent-write-guard.test.sh +51 -0
- package/tests/write-empty-content-guard.test.sh +39 -0
- package/tests/write-nul-corruption-detector.test.sh +29 -0
- package/tests/write-overwrite-unread-content.test.sh +178 -0
- package/tests/wsl-host-disk-space-guard.test.sh +55 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# forbidden-response-phrase-detector.sh — Detect operator-declared forbidden
|
|
3
|
+
# phrases in the assistant's final response.
|
|
4
|
+
#
|
|
5
|
+
# Solves: response-layer recognition-without-arrest where a CLAUDE.md rule
|
|
6
|
+
# prohibiting specific opening or filler phrases is acknowledged by the
|
|
7
|
+
# model and then violated on the next turn (issue #60339).
|
|
8
|
+
#
|
|
9
|
+
# How it works: Stop hook that reads the operator's CLAUDE.md, extracts
|
|
10
|
+
# forbidden response phrases from three operator-natural formats, and
|
|
11
|
+
# checks whether the final assistant response contains any of them. The
|
|
12
|
+
# model's articulation of the rule is no longer load-bearing because the
|
|
13
|
+
# hook reads the rule directly and enforces it at response finalisation.
|
|
14
|
+
#
|
|
15
|
+
# How prohibitions are declared in CLAUDE.md
|
|
16
|
+
# The hook accepts three operator-natural formats. Forbidden phrases must
|
|
17
|
+
# be inside backticks (or smart quotes) for unambiguous extraction. The
|
|
18
|
+
# match is case-insensitive against the response text by default.
|
|
19
|
+
#
|
|
20
|
+
# Format 1 — inline prose:
|
|
21
|
+
# Do NOT open replies with `You're right` or `Great point`.
|
|
22
|
+
# never say `I apologize` in responses.
|
|
23
|
+
#
|
|
24
|
+
# Format 2 — Japanese prose:
|
|
25
|
+
# `了解しました` を返信の冒頭で使うな
|
|
26
|
+
# `はい、その通りです` の使用は禁止
|
|
27
|
+
#
|
|
28
|
+
# Format 3 — list under a "Forbidden Response Phrases" / 禁止 header:
|
|
29
|
+
# ## Forbidden Response Phrases
|
|
30
|
+
# - `You're right`
|
|
31
|
+
# - `Great point`
|
|
32
|
+
# - `I apologize`
|
|
33
|
+
#
|
|
34
|
+
# TRIGGER: Stop
|
|
35
|
+
# MATCHER: ""
|
|
36
|
+
#
|
|
37
|
+
# Configuration:
|
|
38
|
+
# CC_FORBIDDEN_PHRASE_DISABLE=1 Disable the hook entirely.
|
|
39
|
+
# CC_FORBIDDEN_PHRASE_BLOCK=1 Exit non-zero (exit 2) on match. Default:
|
|
40
|
+
# advisory (warn to stderr, exit 0).
|
|
41
|
+
# CC_FORBIDDEN_PHRASE_OPEN_ONLY=1 Only check the first 200 chars of the
|
|
42
|
+
# response (filler-phrase pattern).
|
|
43
|
+
# CC_CLAUDEMD_PATH=/path Override CLAUDE.md search path.
|
|
44
|
+
# CC_FORBIDDEN_PHRASE_CASE_SENSITIVE=1 Case-sensitive match. Default off.
|
|
45
|
+
|
|
46
|
+
set -u
|
|
47
|
+
|
|
48
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
49
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
50
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
51
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
52
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
53
|
+
_nojq_warned="/tmp/cc-nojq-warned-forbidden-response-phrase-detector-$PPID"
|
|
54
|
+
[ -f "$_nojq_warned" ] || {
|
|
55
|
+
echo "WARNING [forbidden-response-phrase-detector]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
56
|
+
: > "$_nojq_warned"
|
|
57
|
+
}
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
[ "${CC_FORBIDDEN_PHRASE_DISABLE:-0}" = "1" ] && exit 0
|
|
61
|
+
|
|
62
|
+
INPUT=$(cat)
|
|
63
|
+
|
|
64
|
+
TRANSCRIPT=$(printf '%s' "$INPUT" | jq -r '.transcript_path // empty' 2>/dev/null)
|
|
65
|
+
[ -z "$TRANSCRIPT" ] && exit 0
|
|
66
|
+
[ ! -r "$TRANSCRIPT" ] && exit 0
|
|
67
|
+
|
|
68
|
+
# Extract the last assistant response from the transcript.
|
|
69
|
+
LAST_ASSISTANT=$(tac "$TRANSCRIPT" 2>/dev/null | grep -m1 '"role":"assistant"' || true)
|
|
70
|
+
[ -z "$LAST_ASSISTANT" ] && exit 0
|
|
71
|
+
|
|
72
|
+
RESPONSE_TEXT=$(printf '%s' "$LAST_ASSISTANT" | jq -r '
|
|
73
|
+
if .message.content then
|
|
74
|
+
(.message.content | if type == "array" then map(select(.type == "text") | .text) | join("\n") else . end)
|
|
75
|
+
elif .content then
|
|
76
|
+
(.content | if type == "array" then map(select(.type == "text") | .text) | join("\n") else . end)
|
|
77
|
+
else
|
|
78
|
+
empty
|
|
79
|
+
end
|
|
80
|
+
' 2>/dev/null)
|
|
81
|
+
|
|
82
|
+
[ -z "$RESPONSE_TEXT" ] && exit 0
|
|
83
|
+
|
|
84
|
+
# Find CLAUDE.md.
|
|
85
|
+
CLAUDEMD=""
|
|
86
|
+
if [ -n "${CC_CLAUDEMD_PATH:-}" ] && [ -r "$CC_CLAUDEMD_PATH" ]; then
|
|
87
|
+
CLAUDEMD="$CC_CLAUDEMD_PATH"
|
|
88
|
+
else
|
|
89
|
+
for candidate in "CLAUDE.md" ".claude/CLAUDE.md" "../CLAUDE.md" "$HOME/.claude/CLAUDE.md"; do
|
|
90
|
+
if [ -r "$candidate" ]; then
|
|
91
|
+
CLAUDEMD="$candidate"
|
|
92
|
+
break
|
|
93
|
+
fi
|
|
94
|
+
done
|
|
95
|
+
fi
|
|
96
|
+
[ -z "$CLAUDEMD" ] && exit 0
|
|
97
|
+
|
|
98
|
+
# Extract forbidden phrases.
|
|
99
|
+
FORBIDDEN_LIST=""
|
|
100
|
+
|
|
101
|
+
# Pass 1: prose prohibitions referring to response/reply behaviour
|
|
102
|
+
PROSE=$(grep -iE '(do[ -]not (open|start|begin|use|say)|never (say|use|open|begin)|を返信|を使うな|の使用は禁止|返信の冒頭|filler|opening)' "$CLAUDEMD" 2>/dev/null || true)
|
|
103
|
+
if [ -n "$PROSE" ]; then
|
|
104
|
+
# Extract backtick-quoted phrases (single backtick form) and curly quotes
|
|
105
|
+
EXTRACTED=$(printf '%s\n' "$PROSE" | grep -oE '`[^`]+`|"[^"]+"' 2>/dev/null | sed -e 's/^`//' -e 's/`$//' -e 's/^"//' -e 's/"$//' | sort -u || true)
|
|
106
|
+
if [ -n "$EXTRACTED" ]; then
|
|
107
|
+
FORBIDDEN_LIST="$EXTRACTED"
|
|
108
|
+
fi
|
|
109
|
+
fi
|
|
110
|
+
|
|
111
|
+
# Pass 2: list items under "Forbidden Response Phrases" / "Forbidden Phrases" / 禁止 headers
|
|
112
|
+
HEADER_LINES=$(grep -inE '^#+ +(forbidden (response )?phrases|forbidden replies|prohibited (response )?phrases|filler phrases|禁止する応答|応答の禁止)' "$CLAUDEMD" 2>/dev/null | cut -d: -f1 || true)
|
|
113
|
+
if [ -n "$HEADER_LINES" ]; then
|
|
114
|
+
for ln in $HEADER_LINES; do
|
|
115
|
+
SECTION=$(sed -n "${ln},$((ln+20))p" "$CLAUDEMD" 2>/dev/null || true)
|
|
116
|
+
ITEMS=$(printf '%s\n' "$SECTION" | grep -E '^[ ]*[-*] +`[^`]+`' 2>/dev/null | grep -oE '`[^`]+`' | sed 's/`//g' || true)
|
|
117
|
+
if [ -n "$ITEMS" ]; then
|
|
118
|
+
FORBIDDEN_LIST="${FORBIDDEN_LIST}${FORBIDDEN_LIST:+$'\n'}${ITEMS}"
|
|
119
|
+
fi
|
|
120
|
+
done
|
|
121
|
+
fi
|
|
122
|
+
|
|
123
|
+
[ -z "$FORBIDDEN_LIST" ] && exit 0
|
|
124
|
+
|
|
125
|
+
FORBIDDEN_LIST=$(printf '%s\n' "$FORBIDDEN_LIST" | sort -u)
|
|
126
|
+
|
|
127
|
+
# Decide scope.
|
|
128
|
+
if [ "${CC_FORBIDDEN_PHRASE_OPEN_ONLY:-0}" = "1" ]; then
|
|
129
|
+
SCOPE=$(printf '%s' "$RESPONSE_TEXT" | head -c 200)
|
|
130
|
+
else
|
|
131
|
+
SCOPE="$RESPONSE_TEXT"
|
|
132
|
+
fi
|
|
133
|
+
|
|
134
|
+
# Match each phrase.
|
|
135
|
+
VIOLATIONS=""
|
|
136
|
+
GREP_FLAGS="-F"
|
|
137
|
+
if [ "${CC_FORBIDDEN_PHRASE_CASE_SENSITIVE:-0}" != "1" ]; then
|
|
138
|
+
GREP_FLAGS="${GREP_FLAGS}i"
|
|
139
|
+
fi
|
|
140
|
+
|
|
141
|
+
while IFS= read -r phrase; do
|
|
142
|
+
[ -z "$phrase" ] && continue
|
|
143
|
+
if printf '%s' "$SCOPE" | grep -q $GREP_FLAGS -- "$phrase" 2>/dev/null; then
|
|
144
|
+
VIOLATIONS="${VIOLATIONS}${VIOLATIONS:+$'\n'}${phrase}"
|
|
145
|
+
fi
|
|
146
|
+
done <<< "$FORBIDDEN_LIST"
|
|
147
|
+
|
|
148
|
+
[ -z "$VIOLATIONS" ] && exit 0
|
|
149
|
+
|
|
150
|
+
# Emit warning.
|
|
151
|
+
echo "⚠ forbidden-response-phrase-detector: assistant response contained phrases prohibited by $CLAUDEMD:" >&2
|
|
152
|
+
printf '%s\n' "$VIOLATIONS" | while IFS= read -r line; do
|
|
153
|
+
[ -n "$line" ] && echo " - \"$line\"" >&2
|
|
154
|
+
done
|
|
155
|
+
echo " See issue #60339 for the failure shape (CLAUDE.md rule re-violated immediately after correction)." >&2
|
|
156
|
+
|
|
157
|
+
if [ "${CC_FORBIDDEN_PHRASE_BLOCK:-0}" = "1" ]; then
|
|
158
|
+
exit 2
|
|
159
|
+
fi
|
|
160
|
+
|
|
161
|
+
exit 0
|
|
@@ -1,5 +1,18 @@
|
|
|
1
|
+
#!/bin/bash
|
|
1
2
|
#
|
|
2
3
|
# TRIGGER: PreToolUse MATCHER: "Bash"
|
|
4
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
5
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
6
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
7
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
8
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
9
|
+
_nojq_warned="/tmp/cc-nojq-warned-gem-push-guard-$PPID"
|
|
10
|
+
[ -f "$_nojq_warned" ] || {
|
|
11
|
+
echo "WARNING [gem-push-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
12
|
+
: > "$_nojq_warned"
|
|
13
|
+
}
|
|
14
|
+
fi
|
|
15
|
+
|
|
3
16
|
INPUT=$(cat)
|
|
4
17
|
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
5
18
|
[[ -z "$COMMAND" ]] && exit 0
|
|
@@ -10,7 +10,19 @@
|
|
|
10
10
|
# The gh CLI is powerful but destructive operations should require
|
|
11
11
|
# explicit human approval, not AI autonomy.
|
|
12
12
|
#
|
|
13
|
-
# TRIGGER: PreToolUse MATCHER: "Bash"
|
|
13
|
+
# TRIGGER: PreToolUse MATCHER: "Bash|PowerShell"
|
|
14
|
+
|
|
15
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
16
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
17
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
18
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
19
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
20
|
+
_nojq_warned="/tmp/cc-nojq-warned-gh-cli-destructive-guard-$PPID"
|
|
21
|
+
[ -f "$_nojq_warned" ] || {
|
|
22
|
+
echo "WARNING [gh-cli-destructive-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
23
|
+
: > "$_nojq_warned"
|
|
24
|
+
}
|
|
25
|
+
fi
|
|
14
26
|
|
|
15
27
|
INPUT=$(cat)
|
|
16
28
|
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
@@ -26,6 +26,18 @@
|
|
|
26
26
|
#
|
|
27
27
|
# TRIGGER: PreToolUse MATCHER: "Bash"
|
|
28
28
|
|
|
29
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
30
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
31
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
32
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
33
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
34
|
+
_nojq_warned="/tmp/cc-nojq-warned-git-checkout-safety-guard-$PPID"
|
|
35
|
+
[ -f "$_nojq_warned" ] || {
|
|
36
|
+
echo "WARNING [git-checkout-safety-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
37
|
+
: > "$_nojq_warned"
|
|
38
|
+
}
|
|
39
|
+
fi
|
|
40
|
+
|
|
29
41
|
INPUT=$(cat)
|
|
30
42
|
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
31
43
|
[ -z "$COMMAND" ] && exit 0
|
|
@@ -23,6 +23,18 @@
|
|
|
23
23
|
#
|
|
24
24
|
# TRIGGER: PreToolUse MATCHER: "Bash"
|
|
25
25
|
|
|
26
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
27
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
28
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
29
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
30
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
31
|
+
_nojq_warned="/tmp/cc-nojq-warned-git-checkout-uncommitted-guard-$PPID"
|
|
32
|
+
[ -f "$_nojq_warned" ] || {
|
|
33
|
+
echo "WARNING [git-checkout-uncommitted-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
34
|
+
: > "$_nojq_warned"
|
|
35
|
+
}
|
|
36
|
+
fi
|
|
37
|
+
|
|
26
38
|
INPUT=$(cat)
|
|
27
39
|
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
28
40
|
|
|
@@ -17,6 +17,18 @@
|
|
|
17
17
|
#
|
|
18
18
|
# TRIGGER: PreToolUse MATCHER: "Bash"
|
|
19
19
|
|
|
20
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
21
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
22
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
23
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
24
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
25
|
+
_nojq_warned="/tmp/cc-nojq-warned-git-config-guard-$PPID"
|
|
26
|
+
[ -f "$_nojq_warned" ] || {
|
|
27
|
+
echo "WARNING [git-config-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
28
|
+
: > "$_nojq_warned"
|
|
29
|
+
}
|
|
30
|
+
fi
|
|
31
|
+
|
|
20
32
|
INPUT=$(cat)
|
|
21
33
|
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
22
34
|
|
|
@@ -14,6 +14,18 @@
|
|
|
14
14
|
# MATCHER: "Bash"
|
|
15
15
|
|
|
16
16
|
set -euo pipefail
|
|
17
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
18
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
19
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
20
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
21
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
22
|
+
_nojq_warned="/tmp/cc-nojq-warned-git-crypt-worktree-guard-$PPID"
|
|
23
|
+
[ -f "$_nojq_warned" ] || {
|
|
24
|
+
echo "WARNING [git-crypt-worktree-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
25
|
+
: > "$_nojq_warned"
|
|
26
|
+
}
|
|
27
|
+
fi
|
|
28
|
+
|
|
17
29
|
INPUT=$(cat)
|
|
18
30
|
|
|
19
31
|
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# git-filter-repo-guard.sh — Block git history rewriting tools
|
|
3
|
+
#
|
|
4
|
+
# Solves: Issue #45893 where `git filter-repo --force` destroyed production
|
|
5
|
+
# files by rewriting repository history. These tools permanently
|
|
6
|
+
# alter commit objects and can cause irreversible data loss.
|
|
7
|
+
#
|
|
8
|
+
# Detects:
|
|
9
|
+
# git filter-repo (modern history rewriter, any arguments)
|
|
10
|
+
# git filter-branch (legacy history rewriter, any arguments)
|
|
11
|
+
# bfg (BFG Repo-Cleaner, third-party history rewriter)
|
|
12
|
+
#
|
|
13
|
+
# TRIGGER: PreToolUse MATCHER: "Bash"
|
|
14
|
+
|
|
15
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
16
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
17
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
18
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
19
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
20
|
+
_nojq_warned="/tmp/cc-nojq-warned-git-filter-repo-guard-$PPID"
|
|
21
|
+
[ -f "$_nojq_warned" ] || {
|
|
22
|
+
echo "WARNING [git-filter-repo-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
23
|
+
: > "$_nojq_warned"
|
|
24
|
+
}
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
INPUT=$(cat)
|
|
28
|
+
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
29
|
+
|
|
30
|
+
[ -z "$COMMAND" ] && exit 0
|
|
31
|
+
|
|
32
|
+
# Block git filter-repo (any arguments)
|
|
33
|
+
if echo "$COMMAND" | grep -qE '\bgit\s+filter-repo\b'; then
|
|
34
|
+
echo "BLOCKED: git filter-repo rewrites repository history (see #45893)." >&2
|
|
35
|
+
echo " This command destroyed production files in a real incident." >&2
|
|
36
|
+
echo " History rewriting is irreversible and breaks all clones." >&2
|
|
37
|
+
exit 2
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
# Block git filter-branch (legacy equivalent)
|
|
41
|
+
if echo "$COMMAND" | grep -qE '\bgit\s+filter-branch\b'; then
|
|
42
|
+
echo "BLOCKED: git filter-branch rewrites repository history (see #45893)." >&2
|
|
43
|
+
echo " Legacy history rewriter — same risks as filter-repo." >&2
|
|
44
|
+
echo " History rewriting is irreversible and breaks all clones." >&2
|
|
45
|
+
exit 2
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
# Block BFG Repo-Cleaner
|
|
49
|
+
if echo "$COMMAND" | grep -qE '\bbfg\b'; then
|
|
50
|
+
echo "BLOCKED: BFG Repo-Cleaner rewrites repository history (see #45893)." >&2
|
|
51
|
+
echo " Third-party tool with the same risks as git filter-repo." >&2
|
|
52
|
+
echo " History rewriting is irreversible and breaks all clones." >&2
|
|
53
|
+
exit 2
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
exit 0
|
|
@@ -20,6 +20,18 @@
|
|
|
20
20
|
#
|
|
21
21
|
# TRIGGER: PreToolUse MATCHER: "Bash"
|
|
22
22
|
|
|
23
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
24
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
25
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
26
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
27
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
28
|
+
_nojq_warned="/tmp/cc-nojq-warned-git-history-rewrite-guard-$PPID"
|
|
29
|
+
[ -f "$_nojq_warned" ] || {
|
|
30
|
+
echo "WARNING [git-history-rewrite-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
31
|
+
: > "$_nojq_warned"
|
|
32
|
+
}
|
|
33
|
+
fi
|
|
34
|
+
|
|
23
35
|
INPUT=$(cat)
|
|
24
36
|
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
25
37
|
|
|
File without changes
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ================================================================
|
|
3
|
+
# git-maintenance-guard.sh — Block automatic git maintenance
|
|
4
|
+
# ================================================================
|
|
5
|
+
# PURPOSE:
|
|
6
|
+
# Claude Code, Codex, and parallel subagents sometimes run
|
|
7
|
+
# git gc / git repack / git maintenance / git prune on their own.
|
|
8
|
+
# When these run concurrently in the same repo, lock contention
|
|
9
|
+
# leaves stale .git/objects/pack/tmp_pack_* files behind. Past
|
|
10
|
+
# incident: 1,350 tmp_pack_* / 144 GiB filled the WSL ext4.vhdx.
|
|
11
|
+
#
|
|
12
|
+
# This hook blocks those maintenance commands at PreToolUse. The
|
|
13
|
+
# user can still run them manually by setting CC_GIT_MAINTENANCE_ALLOW=1
|
|
14
|
+
# for that single command.
|
|
15
|
+
#
|
|
16
|
+
# Detects:
|
|
17
|
+
# git gc (any args)
|
|
18
|
+
# git repack (any args)
|
|
19
|
+
# git maintenance run (any args, including 'start' / 'stop')
|
|
20
|
+
# git prune (any args)
|
|
21
|
+
# git gc --auto (also blocked: still triggers repack)
|
|
22
|
+
#
|
|
23
|
+
# Does NOT block:
|
|
24
|
+
# git gc --prune=now (still blocked — prune is the risky part)
|
|
25
|
+
# read-only inspection: git count-objects, git fsck, git verify-pack
|
|
26
|
+
#
|
|
27
|
+
# TRIGGER: PreToolUse MATCHER: "Bash"
|
|
28
|
+
#
|
|
29
|
+
# CONFIG:
|
|
30
|
+
# CC_GIT_MAINTENANCE_ALLOW=1 one-shot override
|
|
31
|
+
# CC_GIT_MAINTENANCE_DISABLE=1 disable this hook entirely
|
|
32
|
+
# ================================================================
|
|
33
|
+
|
|
34
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
35
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
36
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
37
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
38
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
39
|
+
_nojq_warned="/tmp/cc-nojq-warned-git-maintenance-guard-$PPID"
|
|
40
|
+
[ -f "$_nojq_warned" ] || {
|
|
41
|
+
echo "WARNING [git-maintenance-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
42
|
+
: > "$_nojq_warned"
|
|
43
|
+
}
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
[ "${CC_GIT_MAINTENANCE_DISABLE:-0}" = "1" ] && exit 0
|
|
47
|
+
[ "${CC_GIT_MAINTENANCE_ALLOW:-0}" = "1" ] && exit 0
|
|
48
|
+
|
|
49
|
+
INPUT=$(cat)
|
|
50
|
+
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
51
|
+
|
|
52
|
+
[ -z "$COMMAND" ] && exit 0
|
|
53
|
+
|
|
54
|
+
# git gc (any args)
|
|
55
|
+
if echo "$COMMAND" | grep -qE '(^|[^a-zA-Z0-9._-])git[[:space:]]+gc([[:space:]]|$)'; then
|
|
56
|
+
echo "BLOCKED: git gc can leave stale tmp_pack_* under parallel access." >&2
|
|
57
|
+
echo " Past incident: 1,350 tmp_pack_* / 144 GiB filled the WSL ext4.vhdx." >&2
|
|
58
|
+
echo " Override (one shot): CC_GIT_MAINTENANCE_ALLOW=1 git gc ..." >&2
|
|
59
|
+
exit 2
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
# git repack (any args)
|
|
63
|
+
if echo "$COMMAND" | grep -qE '(^|[^a-zA-Z0-9._-])git[[:space:]]+repack([[:space:]]|$)'; then
|
|
64
|
+
echo "BLOCKED: git repack can leave stale tmp_pack_* under parallel access." >&2
|
|
65
|
+
echo " Override (one shot): CC_GIT_MAINTENANCE_ALLOW=1 git repack ..." >&2
|
|
66
|
+
exit 2
|
|
67
|
+
fi
|
|
68
|
+
|
|
69
|
+
# git maintenance (run / start / stop / register / unregister)
|
|
70
|
+
if echo "$COMMAND" | grep -qE '(^|[^a-zA-Z0-9._-])git[[:space:]]+maintenance([[:space:]]|$)'; then
|
|
71
|
+
echo "BLOCKED: git maintenance schedules background gc/repack — same risk." >&2
|
|
72
|
+
echo " Override (one shot): CC_GIT_MAINTENANCE_ALLOW=1 git maintenance ..." >&2
|
|
73
|
+
exit 2
|
|
74
|
+
fi
|
|
75
|
+
|
|
76
|
+
# git prune (any args). git prune-packed is also caught here, intentionally.
|
|
77
|
+
if echo "$COMMAND" | grep -qE '(^|[^a-zA-Z0-9._-])git[[:space:]]+prune([[:space:]-]|$)'; then
|
|
78
|
+
echo "BLOCKED: git prune removes unreachable objects. Skip unless investigating manually." >&2
|
|
79
|
+
echo " Override (one shot): CC_GIT_MAINTENANCE_ALLOW=1 git prune ..." >&2
|
|
80
|
+
exit 2
|
|
81
|
+
fi
|
|
82
|
+
|
|
83
|
+
exit 0
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -8,27 +8,64 @@
|
|
|
8
8
|
# user approval. This hook enforces the restriction at process level.
|
|
9
9
|
#
|
|
10
10
|
# Blocks:
|
|
11
|
-
# git commit, git push (including --force
|
|
12
|
-
# git switch -c, git branch <name>
|
|
11
|
+
# git commit, git push (including --force and `git send-pack`),
|
|
12
|
+
# git checkout -b, git switch -c, git branch <name> - including when
|
|
13
|
+
# they arrive with git's own global options in front, such as
|
|
14
|
+
# `git -C <dir> push` or `git --git-dir=<path> commit` (#1117).
|
|
13
15
|
#
|
|
14
16
|
# Does NOT block:
|
|
15
17
|
# git status, git log, git diff, git show, git branch (list),
|
|
16
18
|
# git fetch, git stash, git add
|
|
17
19
|
#
|
|
18
|
-
# Handles compound commands (&&, ;,
|
|
20
|
+
# Handles compound commands (&&, ;, ||, |) by checking each segment.
|
|
19
21
|
#
|
|
20
22
|
# See: https://github.com/anthropics/claude-code/issues/40695
|
|
21
23
|
#
|
|
22
24
|
# TRIGGER: PreToolUse MATCHER: "Bash"
|
|
23
25
|
# ================================================================
|
|
24
26
|
|
|
27
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
28
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
29
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
30
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
31
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
32
|
+
_nojq_warned="/tmp/cc-nojq-warned-git-operations-require-approval-$PPID"
|
|
33
|
+
[ -f "$_nojq_warned" ] || {
|
|
34
|
+
echo "WARNING [git-operations-require-approval]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
35
|
+
: > "$_nojq_warned"
|
|
36
|
+
}
|
|
37
|
+
fi
|
|
38
|
+
|
|
25
39
|
INPUT=$(cat)
|
|
26
40
|
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
27
41
|
|
|
28
42
|
[ -z "$COMMAND" ] && exit 0
|
|
29
43
|
|
|
30
|
-
#
|
|
31
|
-
|
|
44
|
+
# git accepts global options between `git` and the subcommand, so matching the
|
|
45
|
+
# two as adjacent words misses every one of these real shapes (reported in #1117
|
|
46
|
+
# with four working examples):
|
|
47
|
+
# git -C /tmp/repo push --force origin main
|
|
48
|
+
# git --git-dir=/tmp/r/repo.d push origin main
|
|
49
|
+
# git -c user.name=x commit -m x
|
|
50
|
+
# git send-pack origin main
|
|
51
|
+
# GIT_OPT is the set of options git itself accepts before a subcommand.
|
|
52
|
+
GIT_OPT='(-[cC][[:space:]]+[^[:space:]]+|--(git-dir|work-tree|namespace|exec-path|config-env|attr-source|super-prefix)(=[^[:space:]]+|[[:space:]]+[^[:space:]]+)|-[pP]|--(paginate|no-pager|bare|no-replace-objects|literal-pathspecs|glob-pathspecs|noglob-pathspecs|icase-pathspecs|no-optional-locks|no-lazy-fetch|no-advice))'
|
|
53
|
+
|
|
54
|
+
# `git` at a command position, not the `git` inside a path. The old pattern
|
|
55
|
+
# matched `git --git-dir=/tmp/r/.git push` only because the *path* ended in
|
|
56
|
+
# `.git`, and let the same command through when the git-dir was named anything
|
|
57
|
+
# else (#1117). Quotes are allowed on purpose: `bash -c "git push ..."` runs.
|
|
58
|
+
GIT_HEAD='(^|[[:space:];&|(]|/|"|'"'"')git'
|
|
59
|
+
|
|
60
|
+
# Build "git [global options] <subcommand>" for one subcommand pattern.
|
|
61
|
+
git_re() {
|
|
62
|
+
printf '%s([[:space:]]+%s)*[[:space:]]+%s' "$GIT_HEAD" "$GIT_OPT" "$1"
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
# Read-only front halves that mention a command without running it.
|
|
66
|
+
# This list is a guess about how people write, not a rule - `sed -i` and any
|
|
67
|
+
# wrapper not named here will still be inspected.
|
|
68
|
+
READ_ONLY_RE='^[[:space:]]*(echo|printf|grep|rg|cat|less|head|tail)[[:space:]]'
|
|
32
69
|
|
|
33
70
|
# Check each segment of compound commands
|
|
34
71
|
check_segment() {
|
|
@@ -37,8 +74,12 @@ check_segment() {
|
|
|
37
74
|
seg=$(echo "$seg" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
|
|
38
75
|
[ -z "$seg" ] && return 0
|
|
39
76
|
|
|
77
|
+
# Exempt only THIS segment. Applying it to the whole command let
|
|
78
|
+
# `echo hi && git push origin main` through completely.
|
|
79
|
+
echo "$seg" | grep -qE "$READ_ONLY_RE" && return 0
|
|
80
|
+
|
|
40
81
|
# git commit
|
|
41
|
-
if echo "$seg" | grep -qE '\
|
|
82
|
+
if echo "$seg" | grep -qE "$(git_re 'commit\b')|${GIT_HEAD}-commit\b"; then
|
|
42
83
|
echo "BLOCKED: git commit requires explicit user approval." >&2
|
|
43
84
|
echo "Command: $seg" >&2
|
|
44
85
|
echo "" >&2
|
|
@@ -47,7 +88,7 @@ check_segment() {
|
|
|
47
88
|
fi
|
|
48
89
|
|
|
49
90
|
# git push (including force variants)
|
|
50
|
-
if echo "$seg" | grep -qE '\
|
|
91
|
+
if echo "$seg" | grep -qE "$(git_re '(push|send-pack)\b')|${GIT_HEAD}-(push|send-pack)\b"; then
|
|
51
92
|
echo "BLOCKED: git push requires explicit user approval." >&2
|
|
52
93
|
echo "Command: $seg" >&2
|
|
53
94
|
echo "" >&2
|
|
@@ -56,14 +97,14 @@ check_segment() {
|
|
|
56
97
|
fi
|
|
57
98
|
|
|
58
99
|
# git checkout -b (branch creation)
|
|
59
|
-
if echo "$seg" | grep -qE '
|
|
100
|
+
if echo "$seg" | grep -qE "$(git_re 'checkout[[:space:]]+(-b|--branch)\b')"; then
|
|
60
101
|
echo "BLOCKED: git branch creation requires explicit user approval." >&2
|
|
61
102
|
echo "Command: $seg" >&2
|
|
62
103
|
return 1
|
|
63
104
|
fi
|
|
64
105
|
|
|
65
106
|
# git switch -c / --create (branch creation)
|
|
66
|
-
if echo "$seg" | grep -qE '
|
|
107
|
+
if echo "$seg" | grep -qE "$(git_re 'switch[[:space:]]+(-c|--create)\b')"; then
|
|
67
108
|
echo "BLOCKED: git branch creation requires explicit user approval." >&2
|
|
68
109
|
echo "Command: $seg" >&2
|
|
69
110
|
return 1
|
|
@@ -71,14 +112,17 @@ check_segment() {
|
|
|
71
112
|
|
|
72
113
|
# git branch <name> (creation, not listing)
|
|
73
114
|
# git branch without flags or with only -a/-r/-l/--list is listing
|
|
74
|
-
if echo "$seg" | grep -qE '
|
|
115
|
+
if echo "$seg" | grep -qE "$(git_re 'branch[[:space:]]')"; then
|
|
75
116
|
# Allow listing flags
|
|
76
|
-
if echo "$seg" | grep -qE '
|
|
117
|
+
if echo "$seg" | grep -qE "$(git_re 'branch[[:space:]]+(-[arl]|--list|--merged|--no-merged|--contains|-v|--verbose|-d|--delete|-D)\b')"; then
|
|
77
118
|
return 0
|
|
78
119
|
fi
|
|
79
120
|
# If it has a name argument after "git branch", it's creation
|
|
80
121
|
local args
|
|
81
|
-
|
|
122
|
+
# The old sed required `git` and `branch` to be adjacent; with a
|
|
123
|
+
# global option in between it stripped nothing and every listing form
|
|
124
|
+
# looked like a creation. Strip up to the subcommand instead.
|
|
125
|
+
args=$(echo "$seg" | sed -E 's/.*[[:space:]]branch[[:space:]]+//')
|
|
82
126
|
if [ -n "$args" ] && ! echo "$args" | grep -qE '^\s*$'; then
|
|
83
127
|
echo "BLOCKED: git branch creation requires explicit user approval." >&2
|
|
84
128
|
echo "Command: $seg" >&2
|
|
@@ -89,11 +133,21 @@ check_segment() {
|
|
|
89
133
|
return 0
|
|
90
134
|
}
|
|
91
135
|
|
|
92
|
-
# Split on && ; || and check each part
|
|
136
|
+
# Split on && ; || | and check each part.
|
|
137
|
+
#
|
|
138
|
+
# A single `|` is a separator too. Without it, a read-only command piped into
|
|
139
|
+
# a git write arrives as ONE segment whose first word is the reader, and
|
|
140
|
+
# READ_ONLY_RE above exempts that whole segment - so the git write on the
|
|
141
|
+
# right-hand side of the pipe is never examined. Measured on the published
|
|
142
|
+
# file 2026-09-15: four piped shapes exited 0 while the same git operations
|
|
143
|
+
# exited 2 when written plainly.
|
|
144
|
+
#
|
|
145
|
+
# `||` is already turned into newlines by the rule before this one, so the
|
|
146
|
+
# single-pipe rule only ever sees real single pipes.
|
|
93
147
|
while IFS= read -r segment; do
|
|
94
148
|
if ! check_segment "$segment"; then
|
|
95
149
|
exit 2
|
|
96
150
|
fi
|
|
97
|
-
done < <(echo "$COMMAND" | sed 's/&&/\n/g; s/;/\n/g; s/||/\n/g')
|
|
151
|
+
done < <(echo "$COMMAND" | sed 's/&&/\n/g; s/;/\n/g; s/||/\n/g; s/|/\n/g')
|
|
98
152
|
|
|
99
153
|
exit 0
|