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
package/examples/edit-guard.sh
CHANGED
|
@@ -19,6 +19,18 @@
|
|
|
19
19
|
#
|
|
20
20
|
# TRIGGER: PreToolUse MATCHER: "Bash"
|
|
21
21
|
|
|
22
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
23
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
24
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
25
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
26
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
27
|
+
_nojq_warned="/tmp/cc-nojq-warned-edit-guard-$PPID"
|
|
28
|
+
[ -f "$_nojq_warned" ] || {
|
|
29
|
+
echo "WARNING [edit-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
30
|
+
: > "$_nojq_warned"
|
|
31
|
+
}
|
|
32
|
+
fi
|
|
33
|
+
|
|
22
34
|
INPUT=$(cat)
|
|
23
35
|
TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
|
|
24
36
|
FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
|
|
@@ -14,6 +14,18 @@
|
|
|
14
14
|
# MATCHER: "Edit"
|
|
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-edit-old-string-validator-$PPID"
|
|
23
|
+
[ -f "$_nojq_warned" ] || {
|
|
24
|
+
echo "WARNING [edit-old-string-validator]: 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
|
FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# edit-quote-ambiguity-guard.sh — Block an Edit that is ambiguous under the
|
|
3
|
+
# tool's own quote-normalization, so it can't silently change the wrong line.
|
|
4
|
+
#
|
|
5
|
+
# Solves (#68962): the Edit tool normalizes typographic quotes when matching
|
|
6
|
+
# old_string (straight " ' are treated as equivalent to curly “ ” ‘ ’), but its
|
|
7
|
+
# uniqueness check counts occurrences of the RAW old_string, not the normalized
|
|
8
|
+
# form. When a file contains curly-quote variants, an old_string written with
|
|
9
|
+
# straight quotes can pass the uniqueness check yet correspond to MORE THAN ONE
|
|
10
|
+
# normalized-equivalent location — the tool then edits the wrong occurrence with
|
|
11
|
+
# no error. Verified on 2.1.179: with
|
|
12
|
+
# message1 = ”hello“ (reversed curly, matches neither raw form)
|
|
13
|
+
# message2 = “hello”
|
|
14
|
+
# an Edit using old_string '"hello"' (replace_all:false) silently rewrote
|
|
15
|
+
# message1 and even mutated its surrounding quote bytes — no ambiguity raised.
|
|
16
|
+
#
|
|
17
|
+
# This guard recomputes the uniqueness check the way the matcher does (over
|
|
18
|
+
# normalized content). It fires ONLY when normalization creates extra matches
|
|
19
|
+
# the raw count can't see (norm_count > raw_count AND norm_count >= 2) — i.e.
|
|
20
|
+
# exactly the silent-wrong-occurrence window. A plain duplicate (raw_count >= 2)
|
|
21
|
+
# is already rejected by the tool itself, so we stay silent there.
|
|
22
|
+
#
|
|
23
|
+
# Precision: BLOCK (exit 2). A silent wrong-line edit is not visible after the
|
|
24
|
+
# fact (that is the whole danger), so prevention beats a non-blocking warning.
|
|
25
|
+
# The fix is cheap: add surrounding context to old_string to make it unique, or
|
|
26
|
+
# set replace_all:true if every variant should change.
|
|
27
|
+
#
|
|
28
|
+
# TRIGGER: PreToolUse MATCHER: "Edit|MultiEdit"
|
|
29
|
+
|
|
30
|
+
# Read the hook payload from stdin into an env var so the heredoc below can be
|
|
31
|
+
# Python's script on stdin without consuming the JSON.
|
|
32
|
+
HOOK_JSON=$(cat)
|
|
33
|
+
export HOOK_JSON
|
|
34
|
+
|
|
35
|
+
python3 <<'PY'
|
|
36
|
+
import os, sys, json
|
|
37
|
+
|
|
38
|
+
try:
|
|
39
|
+
data = json.loads(os.environ.get("HOOK_JSON", ""))
|
|
40
|
+
except Exception:
|
|
41
|
+
sys.exit(0)
|
|
42
|
+
|
|
43
|
+
ti = data.get("tool_input", {}) or {}
|
|
44
|
+
|
|
45
|
+
# MultiEdit carries a list of edits; Edit carries one. Normalize to a list.
|
|
46
|
+
edits = ti.get("edits")
|
|
47
|
+
if not isinstance(edits, list):
|
|
48
|
+
edits = [ti]
|
|
49
|
+
|
|
50
|
+
fp = ti.get("file_path")
|
|
51
|
+
if not fp:
|
|
52
|
+
sys.exit(0)
|
|
53
|
+
|
|
54
|
+
try:
|
|
55
|
+
with open(fp, "r", encoding="utf-8", errors="replace") as fh:
|
|
56
|
+
content = fh.read()
|
|
57
|
+
except Exception:
|
|
58
|
+
sys.exit(0)
|
|
59
|
+
|
|
60
|
+
# Same equivalence relation the matcher uses: fold typographic quotes to ASCII.
|
|
61
|
+
DOUBLE = "“”„‟" # “ ” „ ‟
|
|
62
|
+
SINGLE = "‘’‚‛" # ‘ ’ ‚ ‛
|
|
63
|
+
TBL = {ord(c): '"' for c in DOUBLE}
|
|
64
|
+
TBL.update({ord(c): "'" for c in SINGLE})
|
|
65
|
+
|
|
66
|
+
def norm(s):
|
|
67
|
+
return s.translate(TBL)
|
|
68
|
+
|
|
69
|
+
norm_content = norm(content)
|
|
70
|
+
|
|
71
|
+
for e in edits:
|
|
72
|
+
old = e.get("old_string")
|
|
73
|
+
if old is None or old == "":
|
|
74
|
+
continue
|
|
75
|
+
if e.get("replace_all"):
|
|
76
|
+
continue
|
|
77
|
+
raw_count = content.count(old)
|
|
78
|
+
norm_count = norm_content.count(norm(old))
|
|
79
|
+
# Silent-wrong-occurrence window: normalization reveals matches the raw
|
|
80
|
+
# uniqueness check cannot see, and there is genuine ambiguity (>= 2).
|
|
81
|
+
if norm_count > raw_count and norm_count >= 2:
|
|
82
|
+
msg = (
|
|
83
|
+
"BLOCKED (edit-quote-ambiguity-guard): this Edit's old_string is "
|
|
84
|
+
"ambiguous under the Edit tool's quote-normalization.\n"
|
|
85
|
+
f" old_string matches {raw_count} exact occurrence(s) but "
|
|
86
|
+
f"{norm_count} when straight/curly quotes (\" ' vs “ ” ‘ ’) "
|
|
87
|
+
"are treated as equal.\n"
|
|
88
|
+
" The tool's uniqueness check counts only the raw form, so it can "
|
|
89
|
+
"silently edit the WRONG occurrence (verified, #68962).\n"
|
|
90
|
+
" Fix: add surrounding context to old_string so it is unique in the "
|
|
91
|
+
"file, or set replace_all:true if every variant should change."
|
|
92
|
+
)
|
|
93
|
+
sys.stderr.write(msg + "\n")
|
|
94
|
+
sys.exit(2)
|
|
95
|
+
|
|
96
|
+
sys.exit(0)
|
|
97
|
+
PY
|
|
File without changes
|
package/examples/edit-verify.sh
CHANGED
|
File without changes
|
|
@@ -10,17 +10,29 @@
|
|
|
10
10
|
# If found, blocks with exit 2 and suggests environment variable usage.
|
|
11
11
|
#
|
|
12
12
|
# TRIGGER: PreToolUse
|
|
13
|
-
# MATCHER: "Bash"
|
|
13
|
+
# MATCHER: "Bash|PowerShell"
|
|
14
14
|
|
|
15
15
|
set -euo pipefail
|
|
16
16
|
|
|
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-env-inline-secret-guard-$PPID"
|
|
23
|
+
[ -f "$_nojq_warned" ] || {
|
|
24
|
+
echo "WARNING [env-inline-secret-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
|
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
19
31
|
[ -z "$COMMAND" ] && exit 0
|
|
20
32
|
|
|
21
33
|
# Detect inline secrets: known API key prefixes (20+ chars)
|
|
22
34
|
# sk- (OpenAI), ghp_/ghu_ (GitHub), AKIA (AWS)
|
|
23
|
-
if echo "$COMMAND" | grep -qE '(sk-[
|
|
35
|
+
if echo "$COMMAND" | grep -qE '((^|[^A-Za-z0-9])sk-[A-Za-z0-9_-]{20,}|ghp_[a-zA-Z0-9]{36}|ghu_[a-zA-Z0-9]{36}|AKIA[0-9A-Z]{16}|xoxb-[0-9]+-[0-9]+-[a-zA-Z0-9]+)'; then
|
|
24
36
|
echo "BLOCKED: Possible secret/credential detected in command." >&2
|
|
25
37
|
echo "Use environment variables instead of inline secrets." >&2
|
|
26
38
|
exit 2
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -24,6 +24,18 @@
|
|
|
24
24
|
# - Framework commands that load env properly
|
|
25
25
|
# ================================================================
|
|
26
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-env-source-guard-$PPID"
|
|
33
|
+
[ -f "$_nojq_warned" ] || {
|
|
34
|
+
echo "WARNING [env-source-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
35
|
+
: > "$_nojq_warned"
|
|
36
|
+
}
|
|
37
|
+
fi
|
|
38
|
+
|
|
27
39
|
INPUT=$(cat)
|
|
28
40
|
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
29
41
|
|
|
@@ -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-env-var-check-$PPID"
|
|
26
|
+
[ -f "$_nojq_warned" ] || {
|
|
27
|
+
echo "WARNING [env-var-check]: 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
|
|
|
@@ -31,7 +43,18 @@ if echo "$COMMAND" | grep -qiE 'export\s+(API_KEY|SECRET|TOKEN|PASSWORD|CREDENTI
|
|
|
31
43
|
fi
|
|
32
44
|
|
|
33
45
|
# Check for hardcoded key patterns (sk-, pk-, ghp_, etc.)
|
|
34
|
-
if echo "$COMMAND" | grep -qE 'export\s+\w+=.*(
|
|
46
|
+
if echo "$COMMAND" | grep -qE 'export\s+\w+=.*(ghp_[a-zA-Z0-9]{36}|gho_[a-zA-Z0-9]{36}|glpat-[a-zA-Z0-9]{20,})'; then
|
|
47
|
+
echo "BLOCKED: Hardcoded API key detected in export command" >&2
|
|
48
|
+
echo "Use: export VAR=\$(cat ~/.credentials/key)" >&2
|
|
49
|
+
exit 2
|
|
50
|
+
fi
|
|
51
|
+
|
|
52
|
+
# OpenAI keys. 2026-08: いまの鍵は `sk-proj-` の形で区切りを含むため文字集合に `-` `_` を入れる。
|
|
53
|
+
# 入れると `disk-usage-…` `task-management-…` の中の `sk-` へ当たるので左の境界が要る。
|
|
54
|
+
# ★ただし `export\s+\w+=` が境界にしたい `=` を先に食ってしまうので、
|
|
55
|
+
# 同じ grep の中に書くと `export API_KEY=sk-…` に当たらなくなる(既存のテストで判明)。
|
|
56
|
+
# そこで規則を切り出し、「`=` の直後」と「途中」を分けて書く。
|
|
57
|
+
if echo "$COMMAND" | grep -qE 'export\s+\w+=(sk-[A-Za-z0-9_-]{20,}|.*[^A-Za-z0-9]sk-[A-Za-z0-9_-]{20,})'; then
|
|
35
58
|
echo "BLOCKED: Hardcoded API key detected in export command" >&2
|
|
36
59
|
echo "Use: export VAR=\$(cat ~/.credentials/key)" >&2
|
|
37
60
|
exit 2
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ephemeral-container-detector.sh — Warn operators when Claude Code is
|
|
3
|
+
# starting inside an ephemeral container where MCP approval state will not
|
|
4
|
+
# persist across container recreations.
|
|
5
|
+
#
|
|
6
|
+
# Solves: #61141 — "[BUG] MCP connector permissions lost on every startup
|
|
7
|
+
# in remote/container routines"
|
|
8
|
+
# Reporter: routine running inside an ephemeral container (Docker / devcontainer
|
|
9
|
+
# / Codespaces). The container's HOME tree is regenerated on every startup, so
|
|
10
|
+
# `~/.claude/settings.json` and `mcpServers` approval state are silently wiped.
|
|
11
|
+
# The operator re-approves on first tool call, then loses those approvals at
|
|
12
|
+
# the next container boot. The recovery loop — write to settings.json — itself
|
|
13
|
+
# requires Write approval, producing a blocking approval loop.
|
|
14
|
+
#
|
|
15
|
+
# This hook does NOT attempt to fix the persistence; that requires the
|
|
16
|
+
# operator to mount a persistent volume at the relevant .claude directory or
|
|
17
|
+
# bake an approved settings.json into the container image. Instead the hook
|
|
18
|
+
# surfaces the silent-reset risk on SessionStart so the operator notices it
|
|
19
|
+
# BEFORE the first MCP tool call, rather than after the third approval prompt.
|
|
20
|
+
#
|
|
21
|
+
# Detection runs in two layers. Layer 1: is this an ephemeral runtime?
|
|
22
|
+
# - /.dockerenv exists
|
|
23
|
+
# - /proc/1/cgroup mentions docker, containerd, kubepods, or lxc
|
|
24
|
+
# - $CONTAINER, $DEVCONTAINER, $CODESPACES, $REMOTE_CONTAINERS env set
|
|
25
|
+
# - HOSTNAME matches a short hex pattern typical of container IDs
|
|
26
|
+
# Layer 2: does ~/.claude/ look like it just got recreated?
|
|
27
|
+
# - settings.json missing OR
|
|
28
|
+
# - settings.json has mcpServers configured but no enabledMcpjsonServers /
|
|
29
|
+
# approval state entries (suggests state was wiped)
|
|
30
|
+
#
|
|
31
|
+
# Both layers must hit. Layer 1 alone is too noisy (many container users have
|
|
32
|
+
# correctly mounted ~/.claude/ from a persistent volume). Layer 2 alone is too
|
|
33
|
+
# noisy (a fresh local install also looks like this). Together, the combination
|
|
34
|
+
# is a strong signal that the operator is about to walk into the #61141 loop.
|
|
35
|
+
#
|
|
36
|
+
# TRIGGER: SessionStart
|
|
37
|
+
# MATCHER: ""
|
|
38
|
+
#
|
|
39
|
+
# CONFIGURATION (environment variables):
|
|
40
|
+
# CC_EPHEMERAL_CONTAINER_DISABLE set to "1" to disable
|
|
41
|
+
# CC_CLAUDE_HOME default $HOME/.claude
|
|
42
|
+
#
|
|
43
|
+
# USAGE (settings.json):
|
|
44
|
+
# {
|
|
45
|
+
# "hooks": {
|
|
46
|
+
# "SessionStart": [{
|
|
47
|
+
# "matcher": "",
|
|
48
|
+
# "hooks": [{
|
|
49
|
+
# "type": "command",
|
|
50
|
+
# "command": "~/.claude/hooks/ephemeral-container-detector.sh"
|
|
51
|
+
# }]
|
|
52
|
+
# }]
|
|
53
|
+
# }
|
|
54
|
+
# }
|
|
55
|
+
|
|
56
|
+
set -uo pipefail
|
|
57
|
+
|
|
58
|
+
[ "${CC_EPHEMERAL_CONTAINER_DISABLE:-0}" = "1" ] && exit 0
|
|
59
|
+
|
|
60
|
+
CLAUDE_HOME="${CC_CLAUDE_HOME:-$HOME/.claude}"
|
|
61
|
+
|
|
62
|
+
# --------------------------------------------------------------------------
|
|
63
|
+
# Layer 1 — is this an ephemeral runtime?
|
|
64
|
+
# --------------------------------------------------------------------------
|
|
65
|
+
container_signals=()
|
|
66
|
+
|
|
67
|
+
[ -f /.dockerenv ] && container_signals+=("/.dockerenv file present")
|
|
68
|
+
|
|
69
|
+
if [ -r /proc/1/cgroup ]; then
|
|
70
|
+
if grep -qE 'docker|containerd|kubepods|lxc' /proc/1/cgroup 2>/dev/null; then
|
|
71
|
+
container_signals+=("/proc/1/cgroup names a container runtime")
|
|
72
|
+
fi
|
|
73
|
+
fi
|
|
74
|
+
|
|
75
|
+
[ -n "${CONTAINER:-}" ] && container_signals+=("CONTAINER env set: ${CONTAINER}")
|
|
76
|
+
[ -n "${DEVCONTAINER:-}" ] && container_signals+=("DEVCONTAINER env set")
|
|
77
|
+
[ -n "${CODESPACES:-}" ] && container_signals+=("CODESPACES env set")
|
|
78
|
+
[ -n "${REMOTE_CONTAINERS:-}" ] && container_signals+=("REMOTE_CONTAINERS env set")
|
|
79
|
+
|
|
80
|
+
# Short hex hostnames (e.g. 7b3a1f8d2c4e) are typical of Docker container IDs.
|
|
81
|
+
HOST="${HOSTNAME:-$(hostname 2>/dev/null || echo "")}"
|
|
82
|
+
if [ -n "$HOST" ] && printf '%s' "$HOST" | grep -qE '^[0-9a-f]{8,12}$'; then
|
|
83
|
+
container_signals+=("hostname looks like a container ID: ${HOST}")
|
|
84
|
+
fi
|
|
85
|
+
|
|
86
|
+
[ ${#container_signals[@]} -eq 0 ] && exit 0
|
|
87
|
+
|
|
88
|
+
# --------------------------------------------------------------------------
|
|
89
|
+
# Layer 2 — does ~/.claude/ look freshly recreated?
|
|
90
|
+
# --------------------------------------------------------------------------
|
|
91
|
+
SETTINGS="${CLAUDE_HOME}/settings.json"
|
|
92
|
+
reset_signal=""
|
|
93
|
+
|
|
94
|
+
if [ ! -f "$SETTINGS" ]; then
|
|
95
|
+
reset_signal="settings.json is missing at ${SETTINGS}"
|
|
96
|
+
elif command -v jq >/dev/null 2>&1; then
|
|
97
|
+
# If mcpServers is configured but no approvals are registered, the
|
|
98
|
+
# operator will hit an approval prompt on the first MCP tool call and
|
|
99
|
+
# those approvals will not survive the next container recreation.
|
|
100
|
+
mcp_configured=$(jq -r '
|
|
101
|
+
(.mcpServers // {} | length) +
|
|
102
|
+
(.projects // {} | to_entries[]?.value.mcpServers // {} | length)
|
|
103
|
+
' "$SETTINGS" 2>/dev/null | awk '{s+=$1} END{print s+0}')
|
|
104
|
+
enabled_servers=$(jq -r '
|
|
105
|
+
(.enabledMcpjsonServers // []) | length
|
|
106
|
+
' "$SETTINGS" 2>/dev/null || echo 0)
|
|
107
|
+
|
|
108
|
+
if [ "${mcp_configured:-0}" -gt 0 ] && [ "${enabled_servers:-0}" -eq 0 ]; then
|
|
109
|
+
reset_signal="${mcp_configured} mcpServers configured but enabledMcpjsonServers is empty"
|
|
110
|
+
fi
|
|
111
|
+
fi
|
|
112
|
+
|
|
113
|
+
[ -z "$reset_signal" ] && exit 0
|
|
114
|
+
|
|
115
|
+
# --------------------------------------------------------------------------
|
|
116
|
+
# Both layers hit — emit the advisory.
|
|
117
|
+
# --------------------------------------------------------------------------
|
|
118
|
+
{
|
|
119
|
+
echo ""
|
|
120
|
+
echo "[ephemeral-container-detector] MCP approval state may not persist across container recreations."
|
|
121
|
+
echo ""
|
|
122
|
+
echo "Container signals:"
|
|
123
|
+
for s in "${container_signals[@]}"; do
|
|
124
|
+
echo " - $s"
|
|
125
|
+
done
|
|
126
|
+
echo ""
|
|
127
|
+
echo "Reset signal:"
|
|
128
|
+
echo " - $reset_signal"
|
|
129
|
+
echo ""
|
|
130
|
+
echo "Why this matters (anthropics/claude-code#61141):"
|
|
131
|
+
echo " An ephemeral container regenerates its HOME tree on every boot."
|
|
132
|
+
echo " MCP approvals you grant in this session will be wiped on the next"
|
|
133
|
+
echo " container start. The self-repair path (writing settings.json) also"
|
|
134
|
+
echo " triggers an approval prompt, producing a blocking re-approval loop."
|
|
135
|
+
echo ""
|
|
136
|
+
echo "Mitigations (pick one):"
|
|
137
|
+
echo " 1. Mount a persistent volume at ${CLAUDE_HOME} so settings.json survives."
|
|
138
|
+
echo " 2. Bake an approved settings.json into the container image and"
|
|
139
|
+
echo " declare it read-only so the runtime treats approvals as final."
|
|
140
|
+
echo " 3. Pre-approve specific MCP servers via enabledMcpjsonServers in"
|
|
141
|
+
echo " a settings file under version control."
|
|
142
|
+
echo ""
|
|
143
|
+
echo "Set CC_EPHEMERAL_CONTAINER_DISABLE=1 to silence this warning."
|
|
144
|
+
echo ""
|
|
145
|
+
} >&2
|
|
146
|
+
|
|
147
|
+
exit 0
|
|
@@ -14,6 +14,18 @@
|
|
|
14
14
|
# specifically targets the "same command, same error" pattern.
|
|
15
15
|
# ================================================================
|
|
16
16
|
|
|
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-error-memory-guard-$PPID"
|
|
23
|
+
[ -f "$_nojq_warned" ] || {
|
|
24
|
+
echo "WARNING [error-memory-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
|
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
19
31
|
[ -z "$COMMAND" ] && exit 0
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# evidence-claim-gate.sh — Stop the turn when the assistant claims that
|
|
3
|
+
# evidence was collected ("I tested", "verified", "tests pass", "confirmed",
|
|
4
|
+
# "checked that", "validated") without a corresponding evidence-gathering
|
|
5
|
+
# tool call in the same turn.
|
|
6
|
+
#
|
|
7
|
+
# Solves: #60506 — supplier-side recommendation #5 from the model's own
|
|
8
|
+
# first-person self-report:
|
|
9
|
+
#
|
|
10
|
+
# "Require execution evidence for use of the word 'tested' or its
|
|
11
|
+
# equivalents. The word is currently cheap. The model can emit 'tested'
|
|
12
|
+
# without the test runner having been called in the same turn."
|
|
13
|
+
#
|
|
14
|
+
# Also operationalizes the MAST 3.3 ("No or Incorrect Verification") failure
|
|
15
|
+
# mode documented by Cemri et al. (NeurIPS 2025) and the waitdeadai
|
|
16
|
+
# llm-dark-patterns Stop-hook measurement (F1 0.815, n=19).
|
|
17
|
+
#
|
|
18
|
+
# COMPLEMENTARY TO closure-word-verify-gate.sh:
|
|
19
|
+
# - closure-word-verify-gate.sh catches *completion* claims ("done",
|
|
20
|
+
# "shipped", "production ready") that imply state-is-final.
|
|
21
|
+
# - evidence-claim-gate.sh catches *epistemic* claims ("tested",
|
|
22
|
+
# "verified", "passed") that imply state-was-checked.
|
|
23
|
+
# Both can fire on the same turn; both reduce the same family of failures
|
|
24
|
+
# from different angles.
|
|
25
|
+
#
|
|
26
|
+
# DESIGN PRINCIPLE: false-positive-averse regex. Triggers ONLY on first-person
|
|
27
|
+
# active-voice claim forms ("I tested", "I verified", "tests pass"). Skips
|
|
28
|
+
# future-tense and passive-construction forms ("needs to be tested",
|
|
29
|
+
# "should be verified", "will be checked") where no claim of completed
|
|
30
|
+
# evidence-gathering is being made.
|
|
31
|
+
#
|
|
32
|
+
# Related Issues:
|
|
33
|
+
# #60506 (@zean89, 2026-05-19) — first-person self-report, recommendation 5
|
|
34
|
+
# #60451 (@rkpandey, 2026-05-19) — single-item method claimed supported
|
|
35
|
+
# without static-check evidence
|
|
36
|
+
# #60226 (@suwayama, 2026-05-18) — recognition-without-arrest framework
|
|
37
|
+
# #60188 (@beq00000, 2026-05-18) — agent-malicious-compliance constellation
|
|
38
|
+
# #37818 — fixes declared done without verification
|
|
39
|
+
#
|
|
40
|
+
# Related external work:
|
|
41
|
+
# waitdeadai/llm-dark-patterns — MAST 3.3 deterministic Stop-hook
|
|
42
|
+
# (F1 0.815, CI [0.615, 0.941], κ=1.000 on n=19)
|
|
43
|
+
#
|
|
44
|
+
# TRIGGER: Stop
|
|
45
|
+
# MATCHER: ""
|
|
46
|
+
#
|
|
47
|
+
# CONFIGURATION (environment variables):
|
|
48
|
+
# CC_EVIDENCE_CLAIMS default built-in — regex of first-person evidence
|
|
49
|
+
# claims (pipe-separated)
|
|
50
|
+
# CC_EVIDENCE_COMMANDS default built-in — regex of evidence-gathering
|
|
51
|
+
# tool commands
|
|
52
|
+
# CC_EVIDENCE_GATE_DISABLE set to "1" to disable the gate entirely
|
|
53
|
+
#
|
|
54
|
+
# USAGE (settings.json):
|
|
55
|
+
# {
|
|
56
|
+
# "hooks": {
|
|
57
|
+
# "Stop": [{
|
|
58
|
+
# "matcher": "",
|
|
59
|
+
# "hooks": [{
|
|
60
|
+
# "type": "command",
|
|
61
|
+
# "command": "~/.claude/hooks/evidence-claim-gate.sh"
|
|
62
|
+
# }]
|
|
63
|
+
# }]
|
|
64
|
+
# }
|
|
65
|
+
# }
|
|
66
|
+
|
|
67
|
+
set -uo pipefail
|
|
68
|
+
|
|
69
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
70
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
71
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
72
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
73
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
74
|
+
_nojq_warned="/tmp/cc-nojq-warned-evidence-claim-gate-$PPID"
|
|
75
|
+
[ -f "$_nojq_warned" ] || {
|
|
76
|
+
echo "WARNING [evidence-claim-gate]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
77
|
+
: > "$_nojq_warned"
|
|
78
|
+
}
|
|
79
|
+
fi
|
|
80
|
+
|
|
81
|
+
[ "${CC_EVIDENCE_GATE_DISABLE:-0}" = "1" ] && exit 0
|
|
82
|
+
|
|
83
|
+
INPUT=$(cat 2>/dev/null || true)
|
|
84
|
+
[ -z "$INPUT" ] && exit 0
|
|
85
|
+
|
|
86
|
+
# First-person active-voice evidence claim patterns. Calibrated to fire on
|
|
87
|
+
# claims that evidence was collected, not on future/passive forms.
|
|
88
|
+
# Each branch matches a distinct claim shape; the regex avoids matching
|
|
89
|
+
# negations and modal verbs that indicate no claim is being made.
|
|
90
|
+
DEFAULT_CLAIMS="(\\bi('ve|[[:space:]]+have)?[[:space:]]+(tested|verified|confirmed|validated|checked)\\b|\\b(tests?[[:space:]]+(now[[:space:]]+)?pass(es|ed|ing)?\\b)|\\ball[[:space:]]+tests?[[:space:]]+pass|\\bverified[[:space:]]+(that|the)\\b|\\bconfirmed[[:space:]]+(that|the|it)\\b|\\bvalidated[[:space:]]+(that|the)\\b|\\bchecked[[:space:]]+(that|the)\\b)"
|
|
91
|
+
|
|
92
|
+
# Evidence-gathering commands. Broader than the closure-gate set — also
|
|
93
|
+
# includes read/grep/inspect commands because epistemic claims can be
|
|
94
|
+
# grounded in inspection, not just test runs.
|
|
95
|
+
DEFAULT_COMMANDS='(npm[[:space:]]+(run[[:space:]]+)?test|pytest|playwright|cypress|jest[[:space:]]|vitest|bun[[:space:]]+test|cargo[[:space:]]+test|go[[:space:]]+test|mocha|phpunit|rspec|curl[[:space:]].*localhost|gh[[:space:]]+pr[[:space:]]+checks|deno[[:space:]]+test|tox|make[[:space:]]+test|grep[[:space:]]|rg[[:space:]]|ts-prune|psql|sqlite3|mysql[[:space:]]|redis-cli|jq[[:space:]]|cat[[:space:]]|head[[:space:]]|tail[[:space:]]|wc[[:space:]]|ls[[:space:]]|find[[:space:]]|git[[:space:]]+log|git[[:space:]]+diff|git[[:space:]]+show|git[[:space:]]+status|file[[:space:]])'
|
|
96
|
+
|
|
97
|
+
CLAIMS="${CC_EVIDENCE_CLAIMS:-$DEFAULT_CLAIMS}"
|
|
98
|
+
COMMANDS="${CC_EVIDENCE_COMMANDS:-$DEFAULT_COMMANDS}"
|
|
99
|
+
|
|
100
|
+
# Stop-hook input shape varies across Claude Code versions; try several keys
|
|
101
|
+
# to locate the assistant's most recent message text.
|
|
102
|
+
ASSISTANT_TEXT=$(printf '%s' "$INPUT" | jq -r '
|
|
103
|
+
.transcript[-1].content //
|
|
104
|
+
.last_assistant_message //
|
|
105
|
+
.stop_input.assistant_text //
|
|
106
|
+
.assistant_message //
|
|
107
|
+
empty
|
|
108
|
+
' 2>/dev/null)
|
|
109
|
+
|
|
110
|
+
# Tool calls that ran in this turn. The hook accepts both bash command
|
|
111
|
+
# strings (Bash tool) and tool names (Read/Grep/Glob/Edit, etc.) because
|
|
112
|
+
# epistemic claims can be grounded in either layer.
|
|
113
|
+
TURN_TOOLS=$(printf '%s' "$INPUT" | jq -r '
|
|
114
|
+
[ .turn_tool_calls[]?.command,
|
|
115
|
+
.turn_tool_calls[]?.tool_name,
|
|
116
|
+
.recent_commands[]?,
|
|
117
|
+
.transcript[-1].tool_calls[]?.input.command,
|
|
118
|
+
.transcript[-1].tool_calls[]?.name,
|
|
119
|
+
.last_turn_commands[]?
|
|
120
|
+
] | map(select(. != null)) | .[]
|
|
121
|
+
' 2>/dev/null || true)
|
|
122
|
+
|
|
123
|
+
# Read-class tool names also count as evidence-gathering for inspection
|
|
124
|
+
# claims ("I checked", "verified that"). Map them to the same canonical set.
|
|
125
|
+
READ_TOOLS_PATTERN='\b(Read|Grep|Glob|WebFetch|WebSearch|Bash)\b'
|
|
126
|
+
|
|
127
|
+
# If we cannot find the assistant text, the harness shape differs and we
|
|
128
|
+
# refuse to false-positive — exit silently.
|
|
129
|
+
[ -z "$ASSISTANT_TEXT" ] && exit 0
|
|
130
|
+
|
|
131
|
+
# Negation guard: if the assistant explicitly says "not tested yet" or
|
|
132
|
+
# "needs to be tested" or similar, skip the gate to avoid flagging
|
|
133
|
+
# disclosed un-verified state.
|
|
134
|
+
NEGATION_PATTERNS='(not[[:space:]]+(yet[[:space:]]+)?(tested|verified|checked|confirmed|validated)|needs?[[:space:]]+to[[:space:]]+be[[:space:]]+(tested|verified|checked|confirmed|validated)|should[[:space:]]+be[[:space:]]+(tested|verified|checked|confirmed|validated)|will[[:space:]]+(be[[:space:]]+)?(test|verify|check|confirm|validate)|pending[[:space:]]+verification|untested|unverified)'
|
|
135
|
+
|
|
136
|
+
# Look for an evidence claim in the assistant text.
|
|
137
|
+
MATCHED_CLAIM=$(printf '%s' "$ASSISTANT_TEXT" | grep -Eio "$CLAIMS" | head -1)
|
|
138
|
+
[ -z "$MATCHED_CLAIM" ] && exit 0
|
|
139
|
+
|
|
140
|
+
# Found a claim. Now check whether the entire turn ALSO contains a negation
|
|
141
|
+
# pattern that would qualify the claim. If so, treat as disclosed unverified.
|
|
142
|
+
if printf '%s' "$ASSISTANT_TEXT" | grep -Eiq "$NEGATION_PATTERNS"; then
|
|
143
|
+
# Disclosed unverified state — operator is informed; do not gate.
|
|
144
|
+
exit 0
|
|
145
|
+
fi
|
|
146
|
+
|
|
147
|
+
# Did evidence-gathering happen in the same turn?
|
|
148
|
+
if [ -n "$TURN_TOOLS" ]; then
|
|
149
|
+
if printf '%s' "$TURN_TOOLS" | grep -Eiq "$COMMANDS"; then
|
|
150
|
+
exit 0
|
|
151
|
+
fi
|
|
152
|
+
if printf '%s' "$TURN_TOOLS" | grep -Eq "$READ_TOOLS_PATTERN"; then
|
|
153
|
+
# Read/Grep/Glob/WebFetch were used — inspection evidence is present.
|
|
154
|
+
exit 0
|
|
155
|
+
fi
|
|
156
|
+
fi
|
|
157
|
+
|
|
158
|
+
# Evidence claim without evidence-gathering → block the Stop.
|
|
159
|
+
cat >&2 <<EOF
|
|
160
|
+
<system-reminder>
|
|
161
|
+
EVIDENCE CLAIM WITHOUT EVIDENCE — the phrase "$MATCHED_CLAIM" appears in this
|
|
162
|
+
turn, but no evidence-gathering tool call (test runner, grep, read, curl,
|
|
163
|
+
inspection command) ran in the same turn to substantiate it.
|
|
164
|
+
|
|
165
|
+
This is the failure mode documented in #60506 (recommendation 5) and the MAST
|
|
166
|
+
3.3 ("No or Incorrect Verification") taxonomy: the model emits an epistemic
|
|
167
|
+
claim about state-having-been-checked, but the runtime has no record of the
|
|
168
|
+
checking having happened. The cost of an ungrounded "$MATCHED_CLAIM" lands
|
|
169
|
+
on the operator, not on the model.
|
|
170
|
+
|
|
171
|
+
Before ending this turn, either:
|
|
172
|
+
|
|
173
|
+
1. Run an evidence-gathering command (test runner, grep, read of the
|
|
174
|
+
relevant file, curl-against-localhost, inspection query) that
|
|
175
|
+
substantiates the claim, and re-state the claim only after the evidence
|
|
176
|
+
is in the turn history, OR
|
|
177
|
+
2. Replace "$MATCHED_CLAIM" with a disclosed-unverified form ("not yet
|
|
178
|
+
tested — pending <specific check>", "the code should be verified by
|
|
179
|
+
<specific tool>") so the operator knows the claim is not yet grounded.
|
|
180
|
+
|
|
181
|
+
To disable this gate intentionally (for design discussions, retrospectives,
|
|
182
|
+
documentation work where no evidence is expected), set CC_EVIDENCE_GATE_DISABLE=1
|
|
183
|
+
in your environment.
|
|
184
|
+
</system-reminder>
|
|
185
|
+
EOF
|
|
186
|
+
|
|
187
|
+
exit 2
|
|
@@ -11,6 +11,18 @@
|
|
|
11
11
|
#
|
|
12
12
|
# TRIGGER: PreToolUse MATCHER: "Read|Glob|Grep|Edit|Write"
|
|
13
13
|
|
|
14
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
15
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
16
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
17
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
18
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
19
|
+
_nojq_warned="/tmp/cc-nojq-warned-exploration-budget-guard-$PPID"
|
|
20
|
+
[ -f "$_nojq_warned" ] || {
|
|
21
|
+
echo "WARNING [exploration-budget-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
22
|
+
: > "$_nojq_warned"
|
|
23
|
+
}
|
|
24
|
+
fi
|
|
25
|
+
|
|
14
26
|
INPUT=$(cat)
|
|
15
27
|
TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
|
|
16
28
|
|
|
@@ -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-expo-eject-guard-$PPID"
|
|
10
|
+
[ -f "$_nojq_warned" ] || {
|
|
11
|
+
echo "WARNING [expo-eject-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
|