cc-safe-setup 29.8.0 → 30.0.5
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 +421 -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 +1718 -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,102 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ================================================================
|
|
3
|
+
# git-pack-temp-cleanup-guard.sh — Stop tmp_pack_* explosion
|
|
4
|
+
# ================================================================
|
|
5
|
+
# PURPOSE:
|
|
6
|
+
# Subagents and parallel git operations leave stale
|
|
7
|
+
# .git/objects/pack/tmp_pack_* files behind when git gc / repack
|
|
8
|
+
# fails or is interrupted. These accumulate without bound and can
|
|
9
|
+
# fill ext4.vhdx (observed: 1,350 files / 144 GB on a single repo).
|
|
10
|
+
#
|
|
11
|
+
# This hook runs before any git command. It removes tmp_pack_*
|
|
12
|
+
# files older than CC_GIT_PACK_AGE_MIN minutes, then checks the
|
|
13
|
+
# remaining total. Above thresholds, it warns or blocks.
|
|
14
|
+
#
|
|
15
|
+
# TRIGGER: PreToolUse MATCHER: "Bash"
|
|
16
|
+
#
|
|
17
|
+
# CONFIG:
|
|
18
|
+
# CC_GIT_PACK_AGE_MIN=60 minutes; older tmp_pack_* are removed
|
|
19
|
+
# CC_GIT_PACK_WARN_GB=1 warn at this many GiB remaining
|
|
20
|
+
# CC_GIT_PACK_STRONG_GB=5 strong warning at this many GiB
|
|
21
|
+
# CC_GIT_PACK_BLOCK_GB=10 block git command at this many GiB
|
|
22
|
+
# CC_GIT_PACK_DISABLE=1 set to disable this hook entirely
|
|
23
|
+
# ================================================================
|
|
24
|
+
|
|
25
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
26
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
27
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
28
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
29
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
30
|
+
_nojq_warned="/tmp/cc-nojq-warned-git-pack-temp-cleanup-guard-$PPID"
|
|
31
|
+
[ -f "$_nojq_warned" ] || {
|
|
32
|
+
echo "WARNING [git-pack-temp-cleanup-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
33
|
+
: > "$_nojq_warned"
|
|
34
|
+
}
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
[ "${CC_GIT_PACK_DISABLE:-0}" = "1" ] && exit 0
|
|
38
|
+
|
|
39
|
+
INPUT=$(cat)
|
|
40
|
+
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
41
|
+
|
|
42
|
+
[ -z "$COMMAND" ] && exit 0
|
|
43
|
+
|
|
44
|
+
# Only act on git commands. \bgit\b matches git as a whole word, so
|
|
45
|
+
# pathnames like /usr/bin/gitlab won't trigger.
|
|
46
|
+
echo "$COMMAND" | grep -qE '(^|[^a-zA-Z0-9._-])git([^a-zA-Z0-9._-]|$)' || exit 0
|
|
47
|
+
|
|
48
|
+
AGE_MIN="${CC_GIT_PACK_AGE_MIN:-60}"
|
|
49
|
+
WARN_GB="${CC_GIT_PACK_WARN_GB:-1}"
|
|
50
|
+
STRONG_GB="${CC_GIT_PACK_STRONG_GB:-5}"
|
|
51
|
+
BLOCK_GB="${CC_GIT_PACK_BLOCK_GB:-10}"
|
|
52
|
+
|
|
53
|
+
# Resolve the .git directory of the current repo. If we are outside a
|
|
54
|
+
# git repo, exit silently — the user's git command will fail on its own.
|
|
55
|
+
GIT_DIR=$(git rev-parse --git-dir 2>/dev/null) || exit 0
|
|
56
|
+
PACK_DIR="$GIT_DIR/objects/pack"
|
|
57
|
+
|
|
58
|
+
[ -d "$PACK_DIR" ] || exit 0
|
|
59
|
+
|
|
60
|
+
# Step 1: remove tmp_pack_* older than AGE_MIN minutes.
|
|
61
|
+
# Use -maxdepth 1 so we never recurse. Only match the literal prefix.
|
|
62
|
+
removed_count=0
|
|
63
|
+
removed_bytes=0
|
|
64
|
+
while IFS= read -r -d '' f; do
|
|
65
|
+
sz=$(stat -c '%s' "$f" 2>/dev/null || echo 0)
|
|
66
|
+
if rm -f "$f" 2>/dev/null; then
|
|
67
|
+
removed_count=$((removed_count + 1))
|
|
68
|
+
removed_bytes=$((removed_bytes + sz))
|
|
69
|
+
fi
|
|
70
|
+
done < <(find "$PACK_DIR" -maxdepth 1 -type f -name 'tmp_pack_*' -mmin "+$AGE_MIN" -print0 2>/dev/null)
|
|
71
|
+
|
|
72
|
+
if [ "$removed_count" -gt 0 ]; then
|
|
73
|
+
removed_mib=$((removed_bytes / 1024 / 1024))
|
|
74
|
+
echo "INFO: git-pack-temp-cleanup-guard removed $removed_count stale tmp_pack_* files (${removed_mib} MiB) older than ${AGE_MIN} min in $PACK_DIR" >&2
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
# Step 2: compute remaining total size of tmp_pack_*.
|
|
78
|
+
remaining_bytes=0
|
|
79
|
+
while IFS= read -r -d '' f; do
|
|
80
|
+
sz=$(stat -c '%s' "$f" 2>/dev/null || echo 0)
|
|
81
|
+
remaining_bytes=$((remaining_bytes + sz))
|
|
82
|
+
done < <(find "$PACK_DIR" -maxdepth 1 -type f -name 'tmp_pack_*' -print0 2>/dev/null)
|
|
83
|
+
|
|
84
|
+
remaining_gb=$((remaining_bytes / 1024 / 1024 / 1024))
|
|
85
|
+
|
|
86
|
+
if [ "$remaining_gb" -ge "$BLOCK_GB" ]; then
|
|
87
|
+
echo "BLOCKED: tmp_pack_* total is ${remaining_gb} GiB in $PACK_DIR (threshold ${BLOCK_GB} GiB)." >&2
|
|
88
|
+
echo " Past incidents accumulated 144 GiB and filled ext4.vhdx." >&2
|
|
89
|
+
echo " Investigate before running more git commands. Inspect with:" >&2
|
|
90
|
+
echo " find \"$PACK_DIR\" -maxdepth 1 -name 'tmp_pack_*' -printf '%s %p\\n'" >&2
|
|
91
|
+
echo " Override (one shot) with: CC_GIT_PACK_DISABLE=1 git ..." >&2
|
|
92
|
+
exit 2
|
|
93
|
+
fi
|
|
94
|
+
|
|
95
|
+
if [ "$remaining_gb" -ge "$STRONG_GB" ]; then
|
|
96
|
+
echo "STRONG WARNING: tmp_pack_* total is ${remaining_gb} GiB in $PACK_DIR (strong threshold ${STRONG_GB} GiB)." >&2
|
|
97
|
+
echo " Investigate parallel git activity before this grows further." >&2
|
|
98
|
+
elif [ "$remaining_gb" -ge "$WARN_GB" ]; then
|
|
99
|
+
echo "WARNING: tmp_pack_* total is ${remaining_gb} GiB in $PACK_DIR (threshold ${WARN_GB} GiB)." >&2
|
|
100
|
+
fi
|
|
101
|
+
|
|
102
|
+
exit 0
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# git-push-blast-radius-guard.sh — Cap a runaway fan-out of git pushes that burns CI minutes
|
|
3
|
+
#
|
|
4
|
+
# Solves: When a bug touches many open PRs, the agent can "fix each branch
|
|
5
|
+
# individually" — cherry-pick the same change onto branch after branch and push
|
|
6
|
+
# each one. Every push to a distinct branch triggers the full CI suite, so the
|
|
7
|
+
# cost scales with the number of branches, not the size of the fix. In #65944 a
|
|
8
|
+
# 1-line lint fix was pushed to 13 PR branches across 3 rounds (~150+ workflow
|
|
9
|
+
# runs), exhausting the entire 2,000-minute monthly GitHub Actions allotment in
|
|
10
|
+
# under 3 hours and tripping an account-level Actions block. The operator's own
|
|
11
|
+
# root-cause note: the correct shape was "fix once on main, let PRs inherit it
|
|
12
|
+
# via rebase — 1 CI run instead of 150+."
|
|
13
|
+
#
|
|
14
|
+
# Existing hooks miss this exact shape:
|
|
15
|
+
# - git-operations-require-approval.sh blocks *every* git push (all-or-nothing,
|
|
16
|
+
# off by default); it never counts how many distinct branches a session has
|
|
17
|
+
# pushed, so it can't tell a normal 1-branch push from a 13-branch fan-out.
|
|
18
|
+
# - same-command-repeat-detector.sh keys on the *same* command repeating; a
|
|
19
|
+
# fan-out pushes a *different* branch each time, so it never matches (the
|
|
20
|
+
# same blind spot loop-detector.sh had before webfetch-runaway-guard.sh).
|
|
21
|
+
# - tool-call-rate-limiter.sh counts *all* tool calls in a short window; pushes
|
|
22
|
+
# spread across hours slip under it and it cannot see "distinct branches."
|
|
23
|
+
# - parallel-batch-size-limiter.sh measures *concurrent* batches, not sequential
|
|
24
|
+
# pushes to many branches across rounds.
|
|
25
|
+
#
|
|
26
|
+
# This counts the SET of distinct branches pushed in a rolling per-session window
|
|
27
|
+
# and, once that set crosses a threshold, surfaces the fix-on-main-then-rebase
|
|
28
|
+
# pattern and (by default) blocks the next branch push — the confirmation the
|
|
29
|
+
# operator wished for ("shouldn't push to more than 2-3 branches without
|
|
30
|
+
# confirmation"). The block is recoverable: raise the threshold, switch to warn,
|
|
31
|
+
# or set off. Re-pushing the *same* branch never inflates the count, so an
|
|
32
|
+
# ordinary edit-push-edit-push loop on one feature branch is untouched; only a
|
|
33
|
+
# genuine multi-branch fan-out trips it. `git push --all` / `--mirror` pushes
|
|
34
|
+
# every local branch at once (maximum blast radius) and is treated as a trip
|
|
35
|
+
# immediately.
|
|
36
|
+
#
|
|
37
|
+
# TRIGGER: PreToolUse MATCHER: "Bash"
|
|
38
|
+
# Config (all optional):
|
|
39
|
+
# CC_PUSH_BLAST_GUARD=block block | warn | off
|
|
40
|
+
# CC_PUSH_BLAST_BLOCK=6 block once this many distinct branches fall in the window
|
|
41
|
+
# CC_PUSH_BLAST_WARN=3 warn (stderr, non-blocking) at this many
|
|
42
|
+
# CC_PUSH_BLAST_WINDOW=3600 rolling window in seconds (default 1 hour)
|
|
43
|
+
# CC_PUSH_BLAST_DIR state dir (default: /tmp/cc-push-blast)
|
|
44
|
+
# Related: https://github.com/anthropics/claude-code/issues/65944
|
|
45
|
+
|
|
46
|
+
INPUT=$(cat)
|
|
47
|
+
|
|
48
|
+
MODE="${CC_PUSH_BLAST_GUARD:-block}"
|
|
49
|
+
[ "$MODE" = "off" ] && exit 0
|
|
50
|
+
|
|
51
|
+
# Only act on Bash. Fail open on anything unexpected.
|
|
52
|
+
TOOL=$(printf '%s' "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
|
|
53
|
+
[ "$TOOL" != "Bash" ] && exit 0
|
|
54
|
+
|
|
55
|
+
COMMAND=$(printf '%s' "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
56
|
+
[ -z "$COMMAND" ] && exit 0
|
|
57
|
+
|
|
58
|
+
# git accepts global options between `git` and the subcommand, so `git push`
|
|
59
|
+
# as two adjacent words never sees `git -C <dir> push` - which is exactly how
|
|
60
|
+
# an agent pushes to branch after branch without changing directory. Reported
|
|
61
|
+
# in #1117. `git send-pack` is the plumbing form of the same operation.
|
|
62
|
+
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))'
|
|
63
|
+
GIT_HEAD='(^|[[:space:];&|(]|/|"|'"'"')git'
|
|
64
|
+
GIT_PUSH_RE="${GIT_HEAD}([[:space:]]+${GIT_OPT})*[[:space:]]+(push|send-pack)\\b|${GIT_HEAD}-(push|send-pack)\\b"
|
|
65
|
+
|
|
66
|
+
# Quick reject: nothing to do unless the command runs `git push` somewhere.
|
|
67
|
+
printf '%s' "$COMMAND" | grep -qE "$GIT_PUSH_RE" || exit 0
|
|
68
|
+
|
|
69
|
+
BLOCK_AT="${CC_PUSH_BLAST_BLOCK:-6}"
|
|
70
|
+
WARN_AT="${CC_PUSH_BLAST_WARN:-3}"
|
|
71
|
+
WINDOW="${CC_PUSH_BLAST_WINDOW:-3600}"
|
|
72
|
+
case "$BLOCK_AT" in ''|*[!0-9]*) exit 0;; esac
|
|
73
|
+
case "$WARN_AT" in ''|*[!0-9]*) exit 0;; esac
|
|
74
|
+
case "$WINDOW" in ''|*[!0-9]*) exit 0;; esac
|
|
75
|
+
|
|
76
|
+
# Key state per session so one session's work never trips another's guard.
|
|
77
|
+
SID=$(printf '%s' "$INPUT" | jq -r '.session_id // "default"' 2>/dev/null)
|
|
78
|
+
case "$SID" in ''|*[!A-Za-z0-9_-]*) SID="default";; esac
|
|
79
|
+
|
|
80
|
+
# ---- Work out which branch(es) this command pushes to --------------------
|
|
81
|
+
# A command may chain several segments (&&, ;, newline, |). Inspect each git
|
|
82
|
+
# push segment and collect the branch name(s) it targets. Unknown/odd shapes
|
|
83
|
+
# fail open (they simply contribute nothing rather than guessing wrong).
|
|
84
|
+
FANOUT=0 # set when --all/--mirror pushes every branch at once
|
|
85
|
+
declare -a BRANCHES=()
|
|
86
|
+
|
|
87
|
+
# Split into segments on shell separators so each `git push ...` is seen alone.
|
|
88
|
+
SEGMENTS=$(printf '%s' "$COMMAND" | tr '\n;|' '\n\n\n' | sed 's/&&/\n/g')
|
|
89
|
+
|
|
90
|
+
while IFS= read -r seg; do
|
|
91
|
+
printf '%s' "$seg" | grep -qE "$GIT_PUSH_RE" || continue
|
|
92
|
+
|
|
93
|
+
# Tokens after the subcommand. The old `sed 's/.*\bgit[[:space:]]+push//'`
|
|
94
|
+
# stripped nothing when a global option sat between `git` and `push`, so the
|
|
95
|
+
# whole command ended up parsed as if it were the argument list (#1117).
|
|
96
|
+
# Walking the tokens has no such failure mode.
|
|
97
|
+
# shellcheck disable=SC2206
|
|
98
|
+
_all=( $seg )
|
|
99
|
+
after=""
|
|
100
|
+
_i=0
|
|
101
|
+
while [ "$_i" -lt "${#_all[@]}" ]; do
|
|
102
|
+
case "${_all[$_i]}" in
|
|
103
|
+
push|send-pack) after="${_all[*]:$((_i + 1))}"; break ;;
|
|
104
|
+
esac
|
|
105
|
+
_i=$((_i + 1))
|
|
106
|
+
done
|
|
107
|
+
|
|
108
|
+
# Whole-repo fan-out: one command, every branch, maximum CI blast radius.
|
|
109
|
+
if printf '%s' "$after" | grep -qE '(^|[[:space:]])(--all|--mirror)([[:space:]]|$)'; then
|
|
110
|
+
FANOUT=1
|
|
111
|
+
continue
|
|
112
|
+
fi
|
|
113
|
+
# shellcheck disable=SC2206
|
|
114
|
+
toks=( $after )
|
|
115
|
+
|
|
116
|
+
refspecs=()
|
|
117
|
+
seen_remote=0
|
|
118
|
+
i=0
|
|
119
|
+
while [ "$i" -lt "${#toks[@]}" ]; do
|
|
120
|
+
t="${toks[$i]}"
|
|
121
|
+
i=$((i + 1))
|
|
122
|
+
case "$t" in
|
|
123
|
+
# Flags that take a separate value -> skip the value too.
|
|
124
|
+
--repo|-o|--push-option|--receive-pack|--exec)
|
|
125
|
+
i=$((i + 1)); continue ;;
|
|
126
|
+
-*) continue ;; # any other flag
|
|
127
|
+
esac
|
|
128
|
+
# First bare token is the remote (origin / upstream / a URL). After that,
|
|
129
|
+
# bare tokens are refspecs (branches).
|
|
130
|
+
if [ "$seen_remote" -eq 0 ]; then
|
|
131
|
+
seen_remote=1
|
|
132
|
+
continue
|
|
133
|
+
fi
|
|
134
|
+
refspecs+=("$t")
|
|
135
|
+
done
|
|
136
|
+
|
|
137
|
+
if [ "${#refspecs[@]}" -eq 0 ]; then
|
|
138
|
+
# `git push` / `git push origin` with no refspec -> current branch.
|
|
139
|
+
cur=$(git rev-parse --abbrev-ref HEAD 2>/dev/null)
|
|
140
|
+
[ -n "$cur" ] && [ "$cur" != "HEAD" ] && BRANCHES+=("$cur")
|
|
141
|
+
continue
|
|
142
|
+
fi
|
|
143
|
+
|
|
144
|
+
for r in "${refspecs[@]}"; do
|
|
145
|
+
# Strip a leading '+' (force) and take the destination side of any colon.
|
|
146
|
+
r="${r#+}"
|
|
147
|
+
dst="${r##*:}"
|
|
148
|
+
# Ignore tag/ref deletions and empty sources.
|
|
149
|
+
[ -z "$dst" ] && continue
|
|
150
|
+
case "$dst" in
|
|
151
|
+
HEAD) cur=$(git rev-parse --abbrev-ref HEAD 2>/dev/null)
|
|
152
|
+
[ -n "$cur" ] && [ "$cur" != "HEAD" ] && BRANCHES+=("$cur"); continue ;;
|
|
153
|
+
esac
|
|
154
|
+
BRANCHES+=("$dst")
|
|
155
|
+
done
|
|
156
|
+
done <<EOF
|
|
157
|
+
$SEGMENTS
|
|
158
|
+
EOF
|
|
159
|
+
|
|
160
|
+
# Nothing identifiable and not a fan-out: fail open.
|
|
161
|
+
if [ "$FANOUT" -eq 0 ] && [ "${#BRANCHES[@]}" -eq 0 ]; then
|
|
162
|
+
exit 0
|
|
163
|
+
fi
|
|
164
|
+
|
|
165
|
+
# ---- Record into the rolling per-session window --------------------------
|
|
166
|
+
STATE_DIR="${CC_PUSH_BLAST_DIR:-/tmp/cc-push-blast}"
|
|
167
|
+
mkdir -p "$STATE_DIR" 2>/dev/null || exit 0
|
|
168
|
+
STATE="$STATE_DIR/$SID"
|
|
169
|
+
|
|
170
|
+
NOW=$(date +%s)
|
|
171
|
+
CUTOFF=$((NOW - WINDOW))
|
|
172
|
+
|
|
173
|
+
# Append "<ts>\t<branch>" for every branch this command pushes.
|
|
174
|
+
for b in "${BRANCHES[@]}"; do
|
|
175
|
+
# Sanitise tab/newline out of the branch name for the state file.
|
|
176
|
+
safe=$(printf '%s' "$b" | tr -d '\t\n')
|
|
177
|
+
[ -n "$safe" ] && printf '%s\t%s\n' "$NOW" "$safe" >> "$STATE" 2>/dev/null
|
|
178
|
+
done
|
|
179
|
+
|
|
180
|
+
# Prune entries older than the window.
|
|
181
|
+
if [ -f "$STATE" ]; then
|
|
182
|
+
awk -F'\t' -v c="$CUTOFF" '$1 ~ /^[0-9]+$/ && $1 >= c' "$STATE" > "$STATE.tmp" 2>/dev/null && mv "$STATE.tmp" "$STATE" 2>/dev/null
|
|
183
|
+
fi
|
|
184
|
+
|
|
185
|
+
# Count DISTINCT branches inside the window.
|
|
186
|
+
if [ -f "$STATE" ]; then
|
|
187
|
+
DISTINCT=$(awk -F'\t' '{print $2}' "$STATE" 2>/dev/null | sort -u | grep -c .)
|
|
188
|
+
else
|
|
189
|
+
DISTINCT=0
|
|
190
|
+
fi
|
|
191
|
+
case "$DISTINCT" in ''|*[!0-9]*) DISTINCT=0;; esac
|
|
192
|
+
|
|
193
|
+
# A whole-repo fan-out is an immediate trip regardless of the counter.
|
|
194
|
+
TRIP=0
|
|
195
|
+
[ "$FANOUT" -eq 1 ] && TRIP=1
|
|
196
|
+
[ "$DISTINCT" -ge "$BLOCK_AT" ] && TRIP=1
|
|
197
|
+
|
|
198
|
+
MINS=$((WINDOW / 60))
|
|
199
|
+
if [ "$FANOUT" -eq 1 ]; then
|
|
200
|
+
SUBJECT="This 'git push --all/--mirror' pushes every local branch at once"
|
|
201
|
+
else
|
|
202
|
+
SUBJECT="This makes ${DISTINCT} distinct branches pushed within ${MINS} min"
|
|
203
|
+
fi
|
|
204
|
+
MSG="${SUBJECT}. Each branch push triggers the full CI suite, so cost scales with branch count: in #65944 a 1-line fix pushed across 13 branches ran ~150+ workflow runs and burned the entire 2,000-minute monthly GitHub Actions allotment in under 3 hours. If you are applying one fix to many branches, stop and use the cheap shape instead: commit the fix once on main (or a single branch), merge it, and let the other branches inherit it via rebase/merge — 1 CI run instead of one per branch. To proceed anyway, raise CC_PUSH_BLAST_BLOCK, set CC_PUSH_BLAST_GUARD=warn to only warn, or =off to disable. State resets after ${WINDOW}s of no pushes: ${STATE}"
|
|
205
|
+
|
|
206
|
+
if [ "$TRIP" -eq 1 ]; then
|
|
207
|
+
if [ "$MODE" = "warn" ]; then
|
|
208
|
+
echo "git-push-blast-radius-guard: $MSG" >&2
|
|
209
|
+
exit 0
|
|
210
|
+
fi
|
|
211
|
+
# block (default): structured decision so the model sees the reason.
|
|
212
|
+
jq -n --arg r "$MSG" '{decision: "block", reason: $r}'
|
|
213
|
+
exit 0
|
|
214
|
+
elif [ "$DISTINCT" -ge "$WARN_AT" ]; then
|
|
215
|
+
echo "git-push-blast-radius-guard: ${DISTINCT} distinct branches pushed within ${MINS} min — each push triggers CI; consider fix-on-main + rebase if applying one change to many branches (#65944). Blocks at ${BLOCK_AT}." >&2
|
|
216
|
+
fi
|
|
217
|
+
|
|
218
|
+
exit 0
|
|
@@ -20,9 +20,30 @@ if echo "$COMMAND" | grep -qE '\bgit\s+remote\s+add\b'; then
|
|
|
20
20
|
echo "Verify this is a trusted repository." >&2
|
|
21
21
|
fi
|
|
22
22
|
|
|
23
|
-
# Check for push to
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
# Check for push to a remote that is not origin.
|
|
24
|
+
#
|
|
25
|
+
# The previous version used `(?!origin\b)`, a lookahead that ERE does not have:
|
|
26
|
+
# grep -E rejected the pattern, returned 2, and the `if` was never true. The
|
|
27
|
+
# warning below could not fire on any input. Deciding "is it origin?" in the
|
|
28
|
+
# shell instead of the pattern removes the need for a lookahead entirely.
|
|
29
|
+
#
|
|
30
|
+
# `git` also accepts global options before the subcommand, so `git -C <dir>
|
|
31
|
+
# push upstream main` has to be matched as well (#1117).
|
|
32
|
+
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))'
|
|
33
|
+
GIT_HEAD='(^|[[:space:];&|(]|/|"|'"'"')git'
|
|
34
|
+
GIT_PUSH_RE="${GIT_HEAD}([[:space:]]+${GIT_OPT})*[[:space:]]+push([[:space:]]|$)"
|
|
35
|
+
|
|
36
|
+
if echo "$COMMAND" | grep -qE "$GIT_PUSH_RE"; then
|
|
37
|
+
# First bare word after `push` is the remote (flags and their values are
|
|
38
|
+
# skipped). No remote at all means the default one, which is fine.
|
|
39
|
+
REMOTE=$(echo "$COMMAND" | awk '{
|
|
40
|
+
for (i = 1; i <= NF; i++) {
|
|
41
|
+
if ($i == "push") { seen = 1; continue }
|
|
42
|
+
if (!seen) continue
|
|
43
|
+
if ($i ~ /^-/) { continue }
|
|
44
|
+
print $i; exit
|
|
45
|
+
}
|
|
46
|
+
}')
|
|
26
47
|
if [ -n "$REMOTE" ] && [ "$REMOTE" != "origin" ]; then
|
|
27
48
|
echo "WARNING: Pushing to non-origin remote: $REMOTE" >&2
|
|
28
49
|
echo "Verify this remote is trusted." >&2
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# git-rm-orphan-wipe-guard.sh — Block whole-working-tree deletion via git
|
|
3
|
+
#
|
|
4
|
+
# Solves: Claude Code (or a careless one-liner it runs) wiping an entire
|
|
5
|
+
# working tree — and its recovery path — with git itself, slipping
|
|
6
|
+
# past the rm-based guards.
|
|
7
|
+
#
|
|
8
|
+
# The #70687 pattern (real loss of 3 years of work + .git history):
|
|
9
|
+
# git checkout --orphan wipe && git rm -rf . --quiet
|
|
10
|
+
# 1. "git checkout --orphan" starts a branch with NO parent commit, so
|
|
11
|
+
# there is no prior commit to restore the files from afterwards.
|
|
12
|
+
# 2. "git rm -rf ." then removes every tracked file from the index AND
|
|
13
|
+
# the working tree.
|
|
14
|
+
# Together the project is gone with no commit to recover from.
|
|
15
|
+
#
|
|
16
|
+
# Why existing guards miss it:
|
|
17
|
+
# - rm-safety-net.sh only fires on a command that STARTS with "rm"
|
|
18
|
+
# (^rm). "git rm ..." starts with "git", so it slips through.
|
|
19
|
+
# - git-checkout-safety-guard.sh Check 1 matches "checkout <letter>";
|
|
20
|
+
# "git checkout --orphan" starts with "-", so it is not matched.
|
|
21
|
+
# - bulk-file-delete-guard.sh only blocks "git rm -rf ." when the file
|
|
22
|
+
# count crosses its threshold, so a small-but-total wipe passes.
|
|
23
|
+
#
|
|
24
|
+
# Detects:
|
|
25
|
+
# git checkout --orphan <name> (detaches from all history)
|
|
26
|
+
# git switch --orphan <name> (same, newer syntax)
|
|
27
|
+
# git rm -r / -rf / --recursive (recursive removal of the tree)
|
|
28
|
+
# git rm . / git rm * (whole-tree target)
|
|
29
|
+
#
|
|
30
|
+
# Does NOT block (no on-disk data loss / normal use):
|
|
31
|
+
# git rm <file> (single tracked file)
|
|
32
|
+
# git rm --cached ... (untracks only; disk files survive)
|
|
33
|
+
# git checkout <branch> / -- file (covered by git-checkout-safety-guard)
|
|
34
|
+
#
|
|
35
|
+
# TRIGGER: PreToolUse MATCHER: "Bash"
|
|
36
|
+
|
|
37
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
38
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
39
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
40
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
41
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
42
|
+
_nojq_warned="/tmp/cc-nojq-warned-git-rm-orphan-wipe-guard-$PPID"
|
|
43
|
+
[ -f "$_nojq_warned" ] || {
|
|
44
|
+
echo "WARNING [git-rm-orphan-wipe-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
45
|
+
: > "$_nojq_warned"
|
|
46
|
+
}
|
|
47
|
+
fi
|
|
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
|
+
# === Check 1: git checkout/switch --orphan (removes the recovery path) ===
|
|
55
|
+
if echo "$COMMAND" | grep -qE '\bgit\s+(checkout|switch)\b[^|;&]*--orphan\b'; then
|
|
56
|
+
echo "BLOCKED: git checkout --orphan starts a branch with no parent commit." >&2
|
|
57
|
+
echo " Followed by 'git rm -rf .' this leaves no commit to recover from (#70687)." >&2
|
|
58
|
+
echo " If you really need an orphan branch, run it yourself outside the agent." >&2
|
|
59
|
+
exit 2
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
# === git rm handling: only the destructive (whole-tree) forms ===
|
|
63
|
+
if echo "$COMMAND" | grep -qE '\bgit\s+rm\b'; then
|
|
64
|
+
# --cached removes from the index only; working-tree files survive. Safe.
|
|
65
|
+
if echo "$COMMAND" | grep -qE '\bgit\s+rm\b[^|;&]*--cached\b'; then
|
|
66
|
+
exit 0
|
|
67
|
+
fi
|
|
68
|
+
|
|
69
|
+
# Check 2: recursive removal (-r / -R / -rf / --recursive)
|
|
70
|
+
if echo "$COMMAND" | grep -qE '\bgit\s+rm\s+(-[a-zA-Z]*[rR][a-zA-Z]*|--recursive)\b'; then
|
|
71
|
+
echo "BLOCKED: git rm -r removes every tracked file in the tree from disk." >&2
|
|
72
|
+
echo " rm-safety-net does not catch this (the command starts with 'git', not 'rm')." >&2
|
|
73
|
+
echo " Delete specific files by name, or use 'git rm --cached' to untrack only." >&2
|
|
74
|
+
exit 2
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
# Check 3: whole-tree target ( . or * ) even without -r
|
|
78
|
+
if echo "$COMMAND" | grep -qE '\bgit\s+rm\b[^|;&]*(\s\.(\s|$)|\s\./(\s|$)|\s\*(\s|$))'; then
|
|
79
|
+
echo "BLOCKED: git rm targeting '.' or '*' removes the whole working tree." >&2
|
|
80
|
+
echo " Delete specific files by name, or use 'git rm --cached' to untrack only." >&2
|
|
81
|
+
exit 2
|
|
82
|
+
fi
|
|
83
|
+
fi
|
|
84
|
+
|
|
85
|
+
exit 0
|
|
@@ -28,6 +28,18 @@
|
|
|
28
28
|
# }
|
|
29
29
|
# ================================================================
|
|
30
30
|
|
|
31
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
32
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
33
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
34
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
35
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
36
|
+
_nojq_warned="/tmp/cc-nojq-warned-git-stash-before-checkout-$PPID"
|
|
37
|
+
[ -f "$_nojq_warned" ] || {
|
|
38
|
+
echo "WARNING [git-stash-before-checkout]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
39
|
+
: > "$_nojq_warned"
|
|
40
|
+
}
|
|
41
|
+
fi
|
|
42
|
+
|
|
31
43
|
INPUT=$(cat)
|
|
32
44
|
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
33
45
|
[ -z "$COMMAND" ] && exit 0
|
|
File without changes
|
|
@@ -1,9 +1,76 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
+
# ================================================================
|
|
3
|
+
# git-submodule-guard.sh — Block the data-destroying variant of
|
|
4
|
+
# `git submodule deinit` before it runs
|
|
5
|
+
# ================================================================
|
|
6
|
+
# PURPOSE:
|
|
7
|
+
# `git submodule deinit -f <path>` (or `--force`) removes the
|
|
8
|
+
# submodule's working tree. The -f / --force flag is exactly what
|
|
9
|
+
# makes git delete a submodule working tree that still has
|
|
10
|
+
# uncommitted or un-added changes. Without -f, git refuses when the
|
|
11
|
+
# submodule has local modifications — that built-in refusal is a
|
|
12
|
+
# safety net, and -f overrides it.
|
|
2
13
|
#
|
|
3
|
-
# TRIGGER: PreToolUse
|
|
14
|
+
# TRIGGER: PreToolUse
|
|
15
|
+
# MATCHER: "Bash"
|
|
16
|
+
#
|
|
17
|
+
# WHY THIS MATTERS:
|
|
18
|
+
# #68920 (2026-06) — asked to tidy up an unused submodule reference,
|
|
19
|
+
# Claude Code ran `git submodule deinit -f` followed by `git rm`,
|
|
20
|
+
# and the submodule's uncommitted edits and .gitignored config
|
|
21
|
+
# (editor settings, etc.) were deleted with no confirmation. This is
|
|
22
|
+
# a path that the usual rm -rf / reset --hard / clean -fd guards do
|
|
23
|
+
# NOT catch, because `deinit` does not look like a destructive
|
|
24
|
+
# command. Recovery is only partial: committed work is in the
|
|
25
|
+
# reflog and staged work survives in the index (restore with
|
|
26
|
+
# `git checkout-index`, not visible to `git fsck`), but edits that
|
|
27
|
+
# were never `git add`-ed are gone.
|
|
28
|
+
#
|
|
29
|
+
# WHAT IT DOES:
|
|
30
|
+
# - `git submodule deinit` WITH -f / --force -> block (exit 2) by
|
|
31
|
+
# default, so the force-override of git's own safety net is
|
|
32
|
+
# stopped before any work is lost. Opt out to warn-only with
|
|
33
|
+
# SUBMODULE_DEINIT_BLOCK=0.
|
|
34
|
+
# - `git submodule deinit` WITHOUT a force flag, or `git submodule
|
|
35
|
+
# rm` -> warn only (exit 0). git itself refuses the unforced
|
|
36
|
+
# deinit when there are local changes, so a reminder is enough.
|
|
37
|
+
#
|
|
38
|
+
# CONFIG:
|
|
39
|
+
# SUBMODULE_DEINIT_BLOCK=1 (default: 1 = block forced deinit; 0 = warn-only)
|
|
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-git-submodule-guard-$PPID"
|
|
47
|
+
[ -f "$_nojq_warned" ] || {
|
|
48
|
+
echo "WARNING [git-submodule-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
49
|
+
: > "$_nojq_warned"
|
|
50
|
+
}
|
|
51
|
+
fi
|
|
52
|
+
|
|
4
53
|
COMMAND=$(cat | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
5
54
|
[ -z "$COMMAND" ] && exit 0
|
|
55
|
+
|
|
56
|
+
BLOCK_MODE="${SUBMODULE_DEINIT_BLOCK:-1}"
|
|
57
|
+
|
|
58
|
+
# Forced deinit: the variant that deletes uncommitted submodule work (#68920).
|
|
59
|
+
# Match `git submodule deinit` followed, within the same command segment
|
|
60
|
+
# (no pipe / && / ; in between), by a -f or --force flag.
|
|
61
|
+
if echo "$COMMAND" | grep -qE '\bgit\s+submodule\s+deinit\b[^|&;]*(-f\b|--force\b)'; then
|
|
62
|
+
if [ "$BLOCK_MODE" = "1" ]; then
|
|
63
|
+
echo "BLOCKED: git-submodule-guard: 'git submodule deinit -f/--force' deletes the submodule working tree, including uncommitted and un-added changes, irreversibly (Claude Code incident #68920)." >&2
|
|
64
|
+
echo " Safer path: commit or 'git stash' your submodule work first, or run 'git submodule deinit' WITHOUT -f (git refuses if there are local changes)." >&2
|
|
65
|
+
echo " To allow for legitimate cleanup: export SUBMODULE_DEINIT_BLOCK=0 (warn-only mode)." >&2
|
|
66
|
+
exit 2
|
|
67
|
+
fi
|
|
68
|
+
echo "WARNING: 'git submodule deinit -f/--force' force-removes the submodule working tree and can delete uncommitted work (#68920). Commit or stash first." >&2
|
|
69
|
+
exit 0
|
|
70
|
+
fi
|
|
71
|
+
|
|
72
|
+
# Unforced deinit / submodule rm: warn only (git's own safety still applies).
|
|
6
73
|
if echo "$COMMAND" | grep -qE '\bgit\s+submodule\s+(deinit|rm)\b'; then
|
|
7
|
-
echo "WARNING: Removing git submodule. This may break builds." >&2
|
|
74
|
+
echo "WARNING: Removing git submodule. This may break builds. Uncommitted submodule changes are at risk; commit or stash first." >&2
|
|
8
75
|
fi
|
|
9
76
|
exit 0
|
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
2
|
#
|
|
3
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-git-tag-guard-$PPID"
|
|
10
|
+
[ -f "$_nojq_warned" ] || {
|
|
11
|
+
echo "WARNING [git-tag-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
|
+
|
|
4
16
|
COMMAND=$(cat | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
5
17
|
[ -z "$COMMAND" ] && exit 0
|
|
6
18
|
if echo "$COMMAND" | grep -qE 'git\s+tag\s+(-a\s+|-d\s+)?v'; then
|
|
File without changes
|
|
File without changes
|
|
@@ -15,6 +15,18 @@
|
|
|
15
15
|
|
|
16
16
|
set -euo pipefail
|
|
17
17
|
|
|
18
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
19
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
20
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
21
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
22
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
23
|
+
_nojq_warned="/tmp/cc-nojq-warned-gitops-drift-guard-$PPID"
|
|
24
|
+
[ -f "$_nojq_warned" ] || {
|
|
25
|
+
echo "WARNING [gitops-drift-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
26
|
+
: > "$_nojq_warned"
|
|
27
|
+
}
|
|
28
|
+
fi
|
|
29
|
+
|
|
18
30
|
INPUT=$(cat)
|
|
19
31
|
TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
|
|
20
32
|
case "$TOOL" in Edit|Write) ;; *) exit 0 ;; esac
|
|
@@ -8,6 +8,18 @@
|
|
|
8
8
|
# TRIGGER: PostToolUse
|
|
9
9
|
# MATCHER: "Write|Edit"
|
|
10
10
|
|
|
11
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
12
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
13
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
14
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
15
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
16
|
+
_nojq_warned="/tmp/cc-nojq-warned-go-vet-after-edit-$PPID"
|
|
17
|
+
[ -f "$_nojq_warned" ] || {
|
|
18
|
+
echo "WARNING [go-vet-after-edit]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
19
|
+
: > "$_nojq_warned"
|
|
20
|
+
}
|
|
21
|
+
fi
|
|
22
|
+
|
|
11
23
|
INPUT=$(cat)
|
|
12
24
|
FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
|
|
13
25
|
[ -z "$FILE" ] && exit 0
|