cc-safe-setup 29.8.0 → 30.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +72 -19
- package/.claude-plugin/plugin.json +1 -1
- package/CONTRIBUTING.md +7 -2
- package/COOKBOOK.md +50 -46
- package/LICENSE +21 -0
- package/MIGRATION.md +8 -8
- package/README.md +419 -512
- package/SAFETY_CHECKLIST.md +15 -7
- package/SERVICES.md +194 -0
- package/SETTINGS_REFERENCE.md +236 -17
- package/SKILL.md +5 -5
- package/TROUBLESHOOTING.md +35 -14
- package/action.yml +12 -4
- package/audit/README.md +84 -0
- package/audit/audit-checklist.md +152 -0
- package/audit/boundary-selftest.sh +85 -0
- package/audit/boundary.sh +123 -0
- package/audit/count-hooks.py +42 -0
- package/audit/find-dead-hooks.sh +82 -0
- package/audit/find-unfirable-rules.sh +142 -0
- package/audit/fire.sh +97 -0
- package/audit/selftest.sh +42 -0
- package/audit/unfirable-selftest.sh +81 -0
- package/audit-web/index.html +9 -9
- package/examples/README.md +54 -17
- package/examples/account-billing-log.sh +98 -0
- package/examples/account-routing-preflight.sh +123 -0
- package/examples/agent-sdk-credit-pool-monitor.sh +145 -0
- package/examples/agent-view-quota-decrement.sh +32 -0
- package/examples/agent-view-quota-warn.sh +94 -0
- package/examples/agents-md-edit-drift-warner.sh +223 -0
- package/examples/agents-md-loader.sh +160 -0
- package/examples/agents-md-sync-checker.sh +102 -0
- package/examples/ai-slop-punctuation-arrest.sh +210 -0
- package/examples/allowlist.sh +70 -10
- package/examples/always-allow-pattern-suggester.sh +125 -0
- package/examples/ansible-vault-guard.sh +2 -1
- package/examples/anthropic-base-url-guard.sh +76 -0
- package/examples/api-busyloop-guard.sh +123 -0
- package/examples/api-endpoint-guard.sh +12 -0
- package/examples/api-key-in-url-guard.sh +17 -1
- package/examples/api-rate-limit-guard.sh +36 -1
- package/examples/api-rate-limit-tracker.sh +12 -0
- package/examples/articulated-scope-capture.sh +101 -0
- package/examples/askuserquestion-autonomy-gate.sh +102 -0
- package/examples/attachment-traversal-guard.sh +118 -0
- package/examples/aup-block-pattern-logger.sh +161 -0
- package/examples/aup-false-positive-helper.sh +124 -0
- package/examples/aup-large-tool-output-warner.sh +282 -0
- package/examples/aup-retry-loop-guard.sh +229 -0
- package/examples/auth-expiry-reminder.sh +157 -0
- package/examples/auth-macos-sleep-detector.sh +185 -0
- package/examples/auth-path-detector.sh +171 -0
- package/examples/auth-status-checker.sh +157 -0
- package/examples/authorized-reconfirmation-detector.sh +195 -0
- package/examples/auto-approve-build.sh +39 -0
- package/examples/auto-approve-cargo.sh +31 -1
- package/examples/auto-approve-docker.sh +35 -0
- package/examples/auto-approve-git-read.sh +37 -14
- package/examples/auto-approve-go.sh +30 -1
- package/examples/auto-approve-gradle.sh +29 -1
- package/examples/auto-approve-make.sh +29 -1
- package/examples/auto-approve-maven.sh +29 -1
- package/examples/auto-approve-python.sh +41 -1
- package/examples/auto-approve-readonly-tools.sh +1 -0
- package/examples/auto-approve-readonly.sh +110 -33
- package/examples/auto-approve-ssh.sh +30 -1
- package/examples/auto-approve-test.sh +44 -0
- package/examples/auto-checkpoint.sh +1 -1
- package/examples/auto-compact-prep.sh +0 -0
- package/examples/auto-git-checkpoint.sh +0 -0
- package/examples/auto-mode-safe-commands.sh +53 -1
- package/examples/auto-mode-safety-enforcer.sh +151 -4
- package/examples/auto-push-session-branch.sh +22 -0
- package/examples/aws-production-guard.sh +13 -1
- package/examples/aws-region-guard.sh +1 -1
- package/examples/background-cost-launch-guard.sh +82 -0
- package/examples/background-task-guard.sh +12 -0
- package/examples/backup-before-refactor.sh +0 -0
- package/examples/banned-command-guard.sh +12 -0
- package/examples/bash-allowlist-secondary-check.sh +157 -0
- package/examples/bash-domain-allowlist.sh +12 -0
- package/examples/bash-fanout-bounded-rewriter.sh +191 -0
- package/examples/bash-heuristic-approver.sh +112 -10
- package/examples/bash-project-fence.sh +194 -0
- package/examples/bash-safety-auto-deny.sh +12 -0
- package/examples/bash-secret-output-detector.sh +44 -3
- package/examples/bash-trace-guard.sh +12 -0
- package/examples/bashrc-safety-check.sh +0 -0
- package/examples/bg-permission-prompt-warner.sh +182 -0
- package/examples/bg-task-cooldown-guard.sh +12 -0
- package/examples/binary-read-detector.sh +135 -0
- package/examples/binary-upload-guard.sh +12 -0
- package/examples/block-database-wipe.sh +35 -10
- package/examples/branch-name-check.sh +8 -3
- package/examples/branch-naming-convention.sh +0 -0
- package/examples/broad-find-guard.sh +12 -0
- package/examples/broad-prefix-session-trap-warner.sh +106 -0
- package/examples/bulk-file-delete-guard.sh +45 -0
- package/examples/bypass-mode-effective-verifier.sh +203 -0
- package/examples/cache-creation-drift-detector.sh +120 -0
- package/examples/cache-residue-detector.sh +195 -0
- package/examples/cache-tier-logger.sh +70 -0
- package/examples/cache-ttl-eviction-detector.sh +149 -0
- package/examples/cargo-publish-guard.sh +14 -1
- package/examples/case-insensitive-path-guard.sh +21 -2
- package/examples/case-sensitive-guard.sh +23 -2
- package/examples/cch-cache-guard.sh +0 -0
- package/examples/cch-sentinel-precommit-guard.sh +47 -0
- package/examples/check-abort-controller.sh +1 -1
- package/examples/check-accessibility.sh +0 -0
- package/examples/check-aria-labels.sh +0 -0
- package/examples/check-before-act-enforcer.sh +12 -0
- package/examples/check-charset-meta.sh +0 -0
- package/examples/check-cookie-flags.sh +0 -0
- package/examples/check-cors-config.sh +0 -0
- package/examples/check-csp-headers.sh +0 -0
- package/examples/check-csrf-protection.sh +0 -0
- package/examples/check-debounce.sh +1 -1
- package/examples/check-dependency-age.sh +0 -0
- package/examples/check-dependency-license.sh +0 -0
- package/examples/check-dockerfile-best-practice.sh +0 -0
- package/examples/check-error-boundaries.sh +0 -0
- package/examples/check-error-class.sh +1 -1
- package/examples/check-error-handling.sh +0 -0
- package/examples/check-error-logging.sh +1 -1
- package/examples/check-error-message.sh +0 -0
- package/examples/check-error-stack.sh +0 -0
- package/examples/check-favicon.sh +0 -0
- package/examples/check-git-hooks-compat.sh +0 -0
- package/examples/check-gitattributes.sh +0 -0
- package/examples/check-https-redirect.sh +0 -0
- package/examples/check-input-validation.sh +0 -0
- package/examples/check-lang-attribute.sh +0 -0
- package/examples/check-npm-scripts-exist.sh +0 -0
- package/examples/check-package-size.sh +0 -0
- package/examples/check-port-availability.sh +0 -0
- package/examples/check-promise-all.sh +1 -1
- package/examples/check-rate-limiting.sh +0 -0
- package/examples/check-return-types.sh +0 -0
- package/examples/check-semantic-versioning.sh +0 -0
- package/examples/check-suspense-fallback.sh +1 -1
- package/examples/check-test-exists.sh +0 -0
- package/examples/check-test-naming.sh +0 -0
- package/examples/check-timeout-cleanup.sh +1 -1
- package/examples/check-tls-version.sh +0 -0
- package/examples/check-unsubscribe.sh +1 -1
- package/examples/check-viewport-meta.sh +0 -0
- package/examples/check-worker-terminate.sh +1 -1
- package/examples/checkpoint-tamper-guard.sh +12 -0
- package/examples/chmod-guard.sh +12 -0
- package/examples/chown-guard.sh +24 -0
- package/examples/ci-workflow-guard.sh +6 -1
- package/examples/claim-verify-detector.sh +109 -0
- package/examples/claim-vs-caveat-checker.sh +77 -0
- package/examples/classifier-fallback-allow.sh +114 -40
- package/examples/claude-cache-gc.sh +1 -0
- package/examples/claude-code-version-pin-advisor.sh +183 -0
- package/examples/claude-md-reinjector.sh +129 -0
- package/examples/claude-md-size-monitor.sh +66 -0
- package/examples/claude-update-budget-guard.sh +123 -0
- package/examples/claude-update-smart.sh +113 -0
- package/examples/claudeignore-enforce-guard.sh +12 -0
- package/examples/claudemd-enforcer.sh +0 -0
- package/examples/claudemd-tool-prohibition.sh +128 -0
- package/examples/clear-command-confirm-guard.sh +32 -15
- package/examples/cli-config-pinning-detector.sh +162 -0
- package/examples/cliff-countdown-advisor.sh +96 -0
- package/examples/clipboard-secret-guard.sh +12 -0
- package/examples/closure-word-verify-gate.sh +150 -0
- package/examples/cloud-cli-guard.sh +39 -2
- package/examples/commit-all-scope-guard.sh +44 -0
- package/examples/commit-message-check.sh +1 -1
- package/examples/commit-message-quality.sh +6 -1
- package/examples/commitment-carry-forward-arrest.sh +361 -0
- package/examples/compact-alert-notification.sh +0 -0
- package/examples/compact-dispatch-watchdog.sh +149 -0
- package/examples/completion-claim-without-verification-detector.sh +207 -0
- package/examples/composer-guard.sh +12 -0
- package/examples/compound-bash-permission-resolver.sh +156 -0
- package/examples/compound-command-allow.sh +1 -1
- package/examples/compound-command-deny-enforcer.sh +183 -0
- package/examples/compound-inject-guard.sh +12 -0
- package/examples/concurrent-edit-lock.sh +12 -0
- package/examples/conflict-marker-guard.sh +12 -0
- package/examples/consecutive-error-breaker.sh +0 -0
- package/examples/console-log-count.sh +1 -0
- package/examples/context-compact-advisor.sh +29 -2
- package/examples/context-length-budget.sh +69 -0
- package/examples/context-threshold-alert.sh +12 -0
- package/examples/context-usage-drift-alert.sh +41 -13
- package/examples/conversation-history-guard.sh +12 -0
- package/examples/core-file-protect-guard.sh +12 -0
- package/examples/cors-star-warn.sh +0 -0
- package/examples/cost-incident-self-audit.sh +162 -0
- package/examples/cowork-claude-md-load-checker.sh +100 -0
- package/examples/cowork-fuse-staleness-watcher.sh +140 -0
- package/examples/cowork-hook-absence-warner.sh +167 -0
- package/examples/cowork-model-picker-advisor.sh +115 -0
- package/examples/credential-exfil-guard.sh +65 -4
- package/examples/credential-file-cat-guard.sh +17 -1
- package/examples/cron-create-receipt.sh +112 -0
- package/examples/cron-modification-guard.sh +12 -0
- package/examples/cross-product-mcp-spawn-detector.sh +178 -0
- package/examples/cwd-project-boundary-guard.sh +0 -0
- package/examples/daemon-zombie-worker-surfacer.sh +118 -0
- package/examples/daily-cost-guard.sh +164 -0
- package/examples/daily-usage-tracker.sh +0 -0
- package/examples/dangerous-pip-flag-guard.sh +12 -0
- package/examples/db-connect-guard.sh +13 -1
- package/examples/denied-action-retry-guard.sh +12 -0
- package/examples/deny-bypass-detector.sh +12 -0
- package/examples/deny-rule-integrity-verifier.sh +181 -0
- package/examples/dependency-install-guard.sh +12 -0
- package/examples/deploy-guard.sh +14 -2
- package/examples/deploy-path-verify-guard.sh +12 -0
- package/examples/deployment-readback-gate.sh +135 -0
- package/examples/deployment-readback-gh-adapter.sh +247 -0
- package/examples/deployment-verify-guard.sh +25 -2
- package/examples/destructive-db-script-write-guard.sh +166 -0
- package/examples/destructive-migration-write-guard.sh +163 -0
- package/examples/diff-size-guard.sh +12 -0
- package/examples/disabled-feature-toggle-advisor.sh +88 -0
- package/examples/disk-partition-guard.sh +12 -0
- package/examples/dispatch-allowlist-preflight.sh +301 -0
- package/examples/dispatch-liveness-watchdog.sh +216 -0
- package/examples/dispatch-receipt.sh +174 -0
- package/examples/django-migrate-guard.sh +12 -0
- package/examples/dns-config-guard.sh +12 -0
- package/examples/docker-dangerous-guard.sh +12 -0
- package/examples/docker-volume-guard.sh +0 -0
- package/examples/dockerfile-latest-guard.sh +1 -0
- package/examples/dotenv-anthropic-key-billing-guard.sh +99 -0
- package/examples/dotenv-commit-guard.sh +12 -0
- package/examples/dotenv-read-guard.sh +12 -0
- package/examples/dotfile-protection-guard.sh +12 -0
- package/examples/dotnet-build-on-edit.sh +1 -1
- package/examples/drizzle-migrate-guard.sh +27 -2
- package/examples/echo-probe-spam-detector.sh +176 -0
- package/examples/edit-counter-test-gate.sh +12 -0
- package/examples/edit-error-counter.sh +1 -1
- package/examples/edit-guard.sh +12 -0
- package/examples/edit-old-string-validator.sh +12 -0
- package/examples/edit-quote-ambiguity-guard.sh +97 -0
- package/examples/edit-retry-loop-guard.sh +0 -0
- package/examples/edit-verify.sh +0 -0
- package/examples/env-inline-secret-guard.sh +14 -2
- package/examples/env-naming-convention.sh +0 -0
- package/examples/env-prod-guard.sh +0 -0
- package/examples/env-required-check.sh +0 -0
- package/examples/env-source-guard.sh +12 -0
- package/examples/env-var-check.sh +24 -1
- package/examples/ephemeral-container-detector.sh +147 -0
- package/examples/error-memory-guard.sh +12 -0
- package/examples/evidence-claim-gate.sh +187 -0
- package/examples/exploration-budget-guard.sh +12 -0
- package/examples/expo-eject-guard.sh +13 -0
- package/examples/extended-thinking-loop-guard.sh +139 -0
- package/examples/extended-thinking-resume-warning.sh +119 -0
- package/examples/extended-thinking-tool-use-mismatch-detector.sh +212 -0
- package/examples/fabricated-command-detector.sh +145 -0
- package/examples/false-disk-full-guard.sh +63 -0
- package/examples/feature-deprecation-detector.sh +109 -0
- package/examples/file-change-tracker.sh +1 -1
- package/examples/file-change-undo-tracker.sh +0 -0
- package/examples/file-edit-backup.sh +63 -14
- package/examples/file-reference-check.sh +0 -0
- package/examples/file-size-limit.sh +12 -0
- package/examples/financial-operation-guard.sh +12 -0
- package/examples/firewall-guard.sh +12 -0
- package/examples/fish-shell-wrapper.sh +125 -7
- package/examples/five-hundred-milestone.sh +1 -0
- package/examples/flask-static-route-guard.sh +89 -0
- package/examples/forbidden-response-phrase-detector.sh +161 -0
- package/examples/gem-push-guard.sh +13 -0
- package/examples/gh-cli-destructive-guard.sh +13 -1
- package/examples/git-checkout-safety-guard.sh +12 -0
- package/examples/git-checkout-uncommitted-guard.sh +12 -0
- package/examples/git-config-guard.sh +12 -0
- package/examples/git-crypt-worktree-guard.sh +12 -0
- package/examples/git-filter-repo-guard.sh +56 -0
- package/examples/git-history-rewrite-guard.sh +12 -0
- package/examples/git-hook-bypass-guard.sh +0 -0
- package/examples/git-maintenance-guard.sh +83 -0
- package/examples/git-merge-conflict-prevent.sh +0 -0
- package/examples/git-message-length-check.sh +0 -0
- package/examples/git-message-length.sh +0 -0
- package/examples/git-operations-require-approval.sh +68 -14
- package/examples/git-pack-temp-cleanup-guard.sh +102 -0
- package/examples/git-push-blast-radius-guard.sh +218 -0
- package/examples/git-remote-guard.sh +24 -3
- package/examples/git-rm-orphan-wipe-guard.sh +85 -0
- package/examples/git-stash-before-checkout.sh +12 -0
- package/examples/git-stash-before-danger.sh +0 -0
- package/examples/git-submodule-guard.sh +69 -2
- package/examples/git-tag-guard.sh +12 -0
- package/examples/github-actions-secret-guard.sh +0 -0
- package/examples/gitignore-check.sh +0 -0
- package/examples/gitops-drift-guard.sh +12 -0
- package/examples/go-mod-tidy-warn.sh +1 -0
- package/examples/go-vet-after-edit.sh +12 -0
- package/examples/goal-iteration-limit-warner.sh +152 -0
- package/examples/grep-nul-false-negative-guard.sh +30 -0
- package/examples/growthbook-flag-monitor.sh +257 -0
- package/examples/hallucination-url-check.sh +1 -1
- package/examples/halt-signal-detector.sh +135 -0
- package/examples/handoff-on-clear.sh +65 -0
- package/examples/hardcoded-ip-guard.sh +1 -0
- package/examples/headless-empty-result-guard.sh +0 -0
- package/examples/headless-stop-guard.sh +0 -0
- package/examples/helm-install-guard.sh +2 -1
- package/examples/home-critical-bash-guard.sh +17 -1
- package/examples/hook-debug-wrapper.sh +6 -2
- package/examples/hook-permission-fixer.sh +0 -0
- package/examples/hook-self-disable-detector.sh +99 -0
- package/examples/hook-stdout-sanitizer.sh +6 -2
- package/examples/hook-tamper-guard.sh +12 -0
- package/examples/idle-session-cost-alert.sh +0 -0
- package/examples/image-dimension-guard.sh +109 -0
- package/examples/image-file-validator.sh +0 -0
- package/examples/iteration-quality-degradation-detector.sh +170 -0
- package/examples/java-compile-on-edit.sh +1 -1
- package/examples/json-syntax-check.sh +0 -0
- package/examples/k8s-production-guard.sh +13 -1
- package/examples/kill-process-guard.sh +12 -0
- package/examples/kubernetes-guard.sh +13 -1
- package/examples/laravel-artisan-guard.sh +13 -0
- package/examples/large-file-guard.sh +1 -1
- package/examples/log-level-guard.sh +0 -0
- package/examples/log-truncation-guard.sh +12 -0
- package/examples/long-session-malformed-tool-call-detector.sh +183 -0
- package/examples/loop-detector.sh +12 -0
- package/examples/magic-number-warn.sh +1 -0
- package/examples/main-branch-warn.sh +12 -0
- package/examples/markdown-link-check.sh +0 -0
- package/examples/max-concurrent-agents.sh +12 -0
- package/examples/max-edit-size-guard.sh +13 -0
- package/examples/max-file-count-guard.sh +0 -0
- package/examples/max-file-delete-count.sh +0 -0
- package/examples/max-function-length.sh +1 -0
- package/examples/max-import-count.sh +0 -0
- package/examples/max-subagent-count.sh +0 -0
- package/examples/mcp-config-freeze.sh +12 -0
- package/examples/mcp-config-poisoning-audit.sh +150 -0
- package/examples/mcp-data-boundary.sh +1 -1
- package/examples/mcp-misdiagnosis-arrest.sh +209 -0
- package/examples/mcp-orphan-leak-warner.sh +49 -0
- package/examples/mcp-permissions-ask-warner.sh +151 -0
- package/examples/mcp-routine-approval-detector.sh +154 -0
- package/examples/mcp-server-allowlist.sh +12 -0
- package/examples/mcp-server-guard.sh +12 -0
- package/examples/mcp-startup-bloat-detector.sh +87 -0
- package/examples/mcp-stdio-compatibility-test.sh +153 -0
- package/examples/mcp-tool-audit-log.sh +0 -0
- package/examples/mcp-tool-guard.sh +101 -1
- package/examples/mcp-warmup-wait.sh +0 -0
- package/examples/memory-chain-audit.sh +56 -0
- package/examples/memory-orphan-detector.sh +188 -0
- package/examples/memory-write-guard.sh +99 -17
- package/examples/migration-verify-guard.sh +12 -0
- package/examples/model-swap-suggester.sh +177 -0
- package/examples/model-version-alert.sh +5 -1
- package/examples/model-version-lock.sh +63 -0
- package/examples/move-delete-sequence-guard.sh +33 -2
- package/examples/multi-file-plan-routing-gate.sh +192 -0
- package/examples/multi-vendor-concurrent-warner.sh +108 -0
- package/examples/multi-window-auth-drift-detector.sh +183 -0
- package/examples/multiline-command-approver.sh +161 -23
- package/examples/nested-background-agent-guard.sh +109 -0
- package/examples/nested-spawn-inflight-guard.sh +178 -0
- package/examples/network-exfil-guard.sh +12 -0
- package/examples/network-guard.sh +12 -0
- package/examples/network-interface-guard.sh +12 -0
- package/examples/nextjs-env-guard.sh +1 -1
- package/examples/no-absolute-import.sh +0 -0
- package/examples/no-alert-confirm-prompt.sh +0 -0
- package/examples/no-anonymous-default-export.sh +0 -0
- package/examples/no-any-type.sh +0 -0
- package/examples/no-any-typescript.sh +1 -0
- package/examples/no-ask-human.sh +12 -0
- package/examples/no-assignment-in-condition.sh +0 -0
- package/examples/no-base64-exfil.sh +12 -0
- package/examples/no-callback-hell.sh +0 -0
- package/examples/no-circular-dependency.sh +0 -0
- package/examples/no-cleartext-storage.sh +0 -0
- package/examples/no-commented-code.sh +0 -0
- package/examples/no-commit-fixup.sh +0 -0
- package/examples/no-console-assert.sh +0 -0
- package/examples/no-console-error-swallow.sh +0 -0
- package/examples/no-console-in-prod.sh +0 -0
- package/examples/no-console-log-commit.sh +12 -0
- package/examples/no-console-log.sh +0 -0
- package/examples/no-console-time.sh +0 -0
- package/examples/no-cors-wildcard.sh +4 -1
- package/examples/no-curl-upload.sh +0 -0
- package/examples/no-dangerouslySetInnerHTML.sh +0 -0
- package/examples/no-dangling-await.sh +1 -0
- package/examples/no-debug-commit.sh +12 -0
- package/examples/no-debug-in-commit.sh +0 -0
- package/examples/no-deep-nesting.sh +0 -0
- package/examples/no-deep-relative-import.sh +1 -0
- package/examples/no-default-credentials.sh +0 -0
- package/examples/no-deploy-friday.sh +13 -1
- package/examples/no-disabled-test.sh +0 -0
- package/examples/no-document-write.sh +0 -0
- package/examples/no-empty-function.sh +0 -0
- package/examples/no-eval-in-template.sh +0 -0
- package/examples/no-eval-template.sh +3 -1
- package/examples/no-eval.sh +0 -0
- package/examples/no-exec-user-input.sh +0 -0
- package/examples/no-fixme-ship.sh +12 -0
- package/examples/no-floating-promises.sh +0 -0
- package/examples/no-force-flag.sh +22 -5
- package/examples/no-force-install.sh +0 -0
- package/examples/no-git-amend.sh +12 -0
- package/examples/no-git-rebase-public.sh +0 -0
- package/examples/no-global-install.sh +12 -0
- package/examples/no-global-state.sh +0 -0
- package/examples/no-hardcoded-port.sh +1 -0
- package/examples/no-hardcoded-url.sh +0 -0
- package/examples/no-helmet-missing.sh +0 -0
- package/examples/no-http-url.sh +1 -0
- package/examples/no-http-without-https.sh +0 -0
- package/examples/no-inline-style.sh +0 -0
- package/examples/no-inline-styles.sh +1 -0
- package/examples/no-innerhtml.sh +0 -0
- package/examples/no-install-global.sh +12 -0
- package/examples/no-jwt-in-url.sh +0 -0
- package/examples/no-large-commit.sh +0 -0
- package/examples/no-localhost-expose.sh +0 -0
- package/examples/no-magic-number.sh +0 -0
- package/examples/no-md5-sha1.sh +0 -0
- package/examples/no-mixed-line-endings.sh +8 -1
- package/examples/no-mutation-in-reducer.sh +0 -0
- package/examples/no-nested-ternary.sh +0 -0
- package/examples/no-network-exfil.sh +0 -0
- package/examples/no-open-redirect.sh +0 -0
- package/examples/no-output-truncation.sh +12 -0
- package/examples/no-package-downgrade.sh +0 -0
- package/examples/no-package-lock-edit.sh +12 -0
- package/examples/no-path-join-user-input.sh +0 -0
- package/examples/no-port-bind.sh +0 -0
- package/examples/no-process-exit.sh +0 -0
- package/examples/no-prototype-pollution.sh +0 -0
- package/examples/no-push-without-ci.sh +0 -0
- package/examples/no-push-without-tests.sh +12 -0
- package/examples/no-raw-password-in-url.sh +0 -0
- package/examples/no-root-user-docker.sh +1 -0
- package/examples/no-root-write.sh +12 -0
- package/examples/no-secrets-in-args.sh +4 -1
- package/examples/no-secrets-in-logs.sh +0 -0
- package/examples/no-sensitive-log.sh +0 -0
- package/examples/no-sleep-in-hooks.sh +0 -0
- package/examples/no-star-import-python.sh +1 -0
- package/examples/no-string-concat-sql.sh +0 -0
- package/examples/no-sudo-guard.sh +12 -0
- package/examples/no-sync-fs.sh +0 -0
- package/examples/no-todo-in-merge.sh +0 -0
- package/examples/no-todo-in-production.sh +1 -0
- package/examples/no-todo-without-issue.sh +0 -0
- package/examples/no-unused-import.sh +0 -0
- package/examples/no-var-keyword.sh +0 -0
- package/examples/no-verify-blocker.sh +12 -0
- package/examples/no-wget-piped-bash.sh +12 -0
- package/examples/no-wildcard-cors.sh +0 -0
- package/examples/no-wildcard-delete.sh +0 -0
- package/examples/no-wildcard-import.sh +0 -0
- package/examples/no-with-statement.sh +0 -0
- package/examples/no-write-outside-src.sh +0 -0
- package/examples/no-xml-external-entity.sh +0 -0
- package/examples/non-english-quality-warner.sh +156 -0
- package/examples/notify-waiting.sh +1 -1
- package/examples/npm-audit-warn.sh +0 -0
- package/examples/npm-global-install-guard.sh +12 -0
- package/examples/npm-publish-guard.sh +12 -0
- package/examples/npm-script-injection.sh +0 -0
- package/examples/npm-supply-chain-guard.sh +0 -0
- package/examples/nuxt-config-guard.sh +1 -0
- package/examples/oauth-refresh-monitor.sh +210 -0
- package/examples/opus-degradation-tracker.sh +187 -0
- package/examples/opus48-routine-task-warning.sh +196 -0
- package/examples/opus48-thinking-wedge-advisor.sh +143 -0
- package/examples/output-credential-scan.sh +1 -1
- package/examples/output-secret-mask.sh +31 -9
- package/examples/output-token-spike-detector.sh +145 -0
- package/examples/package-json-guard.sh +12 -0
- package/examples/package-lock-frozen.sh +12 -0
- package/examples/parallel-batch-size-limiter.sh +121 -0
- package/examples/parallel-cascade-detector.sh +116 -0
- package/examples/partial-view-claim-arrest.sh +174 -0
- package/examples/path-deny-bash-guard.sh +12 -0
- package/examples/path-traversal-guard.sh +12 -0
- package/examples/per-prompt-token-cap.sh +124 -0
- package/examples/permission-audit-log.sh +1 -1
- package/examples/permission-denial-enforcer.sh +12 -0
- package/examples/permission-entry-validator.sh +0 -0
- package/examples/persisted-1m-model-advisor.sh +88 -0
- package/examples/php-lint-on-edit.sh +1 -1
- package/examples/pii-upload-guard.sh +12 -0
- package/examples/pip-publish-guard.sh +13 -0
- package/examples/pip-requirements-guard.sh +12 -0
- package/examples/pip-venv-required.sh +12 -0
- package/examples/plan-mode-edit-guard.sh +12 -0
- package/examples/plan-mode-enforcer.sh +12 -0
- package/examples/plan-mode-strict-guard.sh +12 -0
- package/examples/plugin-hooks-json-bloat-detector.sh +169 -0
- package/examples/plugin-process-cleanup.sh +0 -0
- package/examples/polyglot-rm-guard.sh +12 -0
- package/examples/post-compact-safety.sh +12 -0
- package/examples/post-edit-disk-verify.sh +152 -0
- package/examples/powershell-remove-item-guard.sh +85 -0
- package/examples/pr-description-check.sh +0 -0
- package/examples/pr-duplicate-guard.sh +13 -0
- package/examples/pre-bash-sed-line-ending-windows.sh +87 -0
- package/examples/pre-compact-knowledge-save.sh +0 -0
- package/examples/pre-compact-transcript-backup.sh +0 -0
- package/examples/pre-execution-claim-detector.sh +179 -0
- package/examples/prefer-builtin-tools.sh +10 -1
- package/examples/prefer-const.sh +0 -0
- package/examples/prefer-dedicated-tools.sh +12 -0
- package/examples/prefer-optional-chaining.sh +0 -0
- package/examples/prisma-migrate-guard.sh +24 -7
- package/examples/production-port-kill-guard.sh +12 -0
- package/examples/prompt-injection-guard.sh +2 -1
- package/examples/prompt-usage-logger.sh +0 -0
- package/examples/protect-claudemd.sh +12 -0
- package/examples/protect-dotfiles.sh +12 -0
- package/examples/proxy-capture-suggester.sh +159 -0
- package/examples/public-artefact-socratic-narrowing.sh +232 -0
- package/examples/public-repo-push-guard.sh +12 -0
- package/examples/push-requires-test-pass-record.sh +0 -0
- package/examples/push-requires-test-pass.sh +12 -0
- package/examples/quota-anomaly-detector.sh +173 -0
- package/examples/quota-reset-audit.sh +58 -0
- package/examples/quoted-flag-approver.sh +99 -10
- package/examples/rails-migration-guard.sh +12 -0
- package/examples/rate-limit-guard.sh +0 -0
- package/examples/read-all-files-enforcer.sh +0 -0
- package/examples/read-budget-guard.sh +12 -0
- package/examples/read-loop-detector.sh +59 -0
- package/examples/read-once-guard.sh +96 -0
- package/examples/read-only-mode.sh +12 -0
- package/examples/readme-exists-check.sh +0 -0
- package/examples/record-read-coverage.sh +73 -0
- package/examples/redirect-fragment-warner.sh +149 -0
- package/examples/redis-flushall-guard.sh +13 -0
- package/examples/redundant-read-blocker.sh +132 -0
- package/examples/refusal-arrest-gate.sh +248 -0
- package/examples/registry-publish-guard.sh +13 -1
- package/examples/remote-control-billing-classifier.sh +135 -0
- package/examples/replace-all-guard.sh +12 -0
- package/examples/repo-visibility-guard.sh +12 -0
- package/examples/reroute-after-block-guard.sh +150 -0
- package/examples/response-budget-guard.sh +0 -0
- package/examples/resume-drift-watcher.sh +57 -0
- package/examples/rg-replace-flag-detector.sh +125 -0
- package/examples/rhetorical-verification-prompt-detector.sh +102 -0
- package/examples/ripgrep-permission-fix.sh +0 -0
- package/examples/rm-safety-net.sh +151 -8
- package/examples/role-tool-guard.sh +12 -0
- package/examples/route-handler-emptiness-gate.sh +324 -0
- package/examples/ruby-lint-on-edit.sh +1 -1
- package/examples/runtime-binary-change-detector.sh +102 -0
- package/examples/same-command-repeat-detector.sh +196 -0
- package/examples/same-correction-arrest.sh +169 -0
- package/examples/sandbox-denywrite-enforcer.sh +78 -0
- package/examples/sandbox-relative-path-audit.sh +83 -25
- package/examples/sandbox-write-verify.sh +12 -0
- package/examples/schema-migration-guard.sh +0 -0
- package/examples/scope-expansion-receipt.sh +178 -0
- package/examples/scope-guard.sh +88 -9
- package/examples/secret-file-read-guard.sh +12 -0
- package/examples/secret-file-write-guard.sh +150 -0
- package/examples/self-modify-bypass-guard.sh +0 -0
- package/examples/sensitive-file-read-guard.sh +23 -3
- package/examples/sensitive-log-guard.sh +1 -0
- package/examples/server-side-prompt-injection-detector.sh +69 -0
- package/examples/session-agent-cost-limiter.sh +12 -0
- package/examples/session-backup-on-start.sh +1 -1
- package/examples/session-cost-alert.sh +12 -0
- package/examples/session-drift-guard.sh +12 -0
- package/examples/session-duration-guard.sh +25 -2
- package/examples/session-end-logger.sh +0 -0
- package/examples/session-health-monitor.sh +0 -0
- package/examples/session-index-repair.sh +1 -1
- package/examples/session-memory-watchdog.sh +1 -0
- package/examples/session-permission-reset-guard.sh +12 -0
- package/examples/session-persistence-verifier.sh +93 -0
- package/examples/session-plugin-pin-watch.sh +68 -0
- package/examples/session-rate-monitor.sh +176 -0
- package/examples/session-resume-env-fix.sh +0 -0
- package/examples/session-start-quota-status.sh +193 -0
- package/examples/session-start-safety-check.sh +55 -3
- package/examples/session-state-saver.sh +0 -0
- package/examples/session-summary-stop.sh +1 -1
- package/examples/session-summary.sh +0 -0
- package/examples/session-token-counter.sh +1 -1
- package/examples/settings-hooks-key-restorer.sh +99 -0
- package/examples/settings-json-health-check.sh +57 -0
- package/examples/settings-json-model-guard.sh +0 -0
- package/examples/settings-regression-tester.sh +188 -0
- package/examples/shell-config-truncation-guard.sh +12 -0
- package/examples/shell-wrapper-guard.sh +12 -0
- package/examples/skill-cumulative-size-detector.sh +104 -0
- package/examples/skill-description-drop-detector.sh +148 -0
- package/examples/skill-gate.sh +0 -0
- package/examples/skill-truncation-detector.sh +154 -0
- package/examples/skills-context-recorder.sh +167 -0
- package/examples/skills-load-verifier.sh +96 -0
- package/examples/skills-settings-validator.sh +139 -0
- package/examples/sonnet-45-deprecation-helper.sh +85 -0
- package/examples/spec-file-scope-guard.sh +12 -0
- package/examples/spring-profile-guard.sh +1 -0
- package/examples/spurious-malformed-notice-detector.sh +247 -0
- package/examples/sql-bulk-delete-warn.sh +88 -0
- package/examples/sql-injection-detect.sh +0 -0
- package/examples/ssh-key-protect.sh +12 -0
- package/examples/staged-secret-scan.sh +22 -1
- package/examples/stale-temp-settings-detector.sh +86 -0
- package/examples/standing-rule-session-surfacer.sh +137 -0
- package/examples/stop-hook-sigterm-wrapper.sh +182 -0
- package/examples/stop-transcript-write-health.sh +64 -0
- package/examples/strict-allowlist.sh +57 -15
- package/examples/strip-coauthored-by.sh +50 -10
- package/examples/subagent-blast-radius-guard.sh +184 -0
- package/examples/subagent-boundary-precheck.sh +126 -0
- package/examples/subagent-budget-guard.sh +12 -0
- package/examples/subagent-claudemd-inject.sh +0 -0
- package/examples/subagent-closure-verify-gate.sh +164 -0
- package/examples/subagent-destructive-git-guard.sh +120 -0
- package/examples/subagent-error-detector.sh +0 -0
- package/examples/subagent-forged-system-reminder-guard.sh +156 -0
- package/examples/subagent-identity-leak-guard.sh +102 -0
- package/examples/subagent-identity-reassertion.sh +51 -0
- package/examples/subagent-inheritance-tester.sh +179 -0
- package/examples/subagent-permission-mode-guard.sh +110 -0
- package/examples/subagent-scope-guard.sh +12 -0
- package/examples/subagent-spawn-verification-enforcer.sh +102 -0
- package/examples/subagent-tool-allowlist-enforcer.sh +101 -0
- package/examples/subagent-tool-call-limiter.sh +87 -15
- package/examples/subcommand-chain-guard.sh +12 -0
- package/examples/subscription-api-billing-warner.sh +160 -0
- package/examples/subscription-bypass-detector.sh +152 -0
- package/examples/svelte-lint-on-edit.sh +1 -0
- package/examples/swift-build-on-edit.sh +1 -1
- package/examples/symlink-guard.sh +27 -2
- package/examples/symlink-protect.sh +1 -0
- package/examples/system-dir-protection-guard.sh +73 -8
- package/examples/system-message-workaround.sh +38 -13
- package/examples/system-package-guard.sh +12 -0
- package/examples/systemd-service-guard.sh +12 -0
- package/examples/task-integrity-guard.sh +12 -0
- package/examples/temp-file-cleanup.sh +1 -1
- package/examples/temporal-suggestion-detector.sh +135 -0
- package/examples/terraform-guard.sh +27 -6
- package/examples/test-after-edit.sh +1 -1
- package/examples/test-before-push.sh +12 -0
- package/examples/test-coverage-reminder.sh +24 -1
- package/examples/thinking-budget-effort-mismatch-detector.sh +149 -0
- package/examples/timezone-guard.sh +0 -0
- package/examples/tmp-output-size-guard.sh +0 -0
- package/examples/todo-check.sh +1 -1
- package/examples/token-budget-guard.sh +12 -0
- package/examples/token-budget-per-task.sh +12 -0
- package/examples/token-usage-tracker.sh +7 -1
- package/examples/tokenizer-ratio-alert-corpus.sh +90 -0
- package/examples/tokenizer-ratio-alert.sh +104 -0
- package/examples/tool-call-rate-limiter.sh +0 -0
- package/examples/tool-result-correlation-checker.sh +167 -0
- package/examples/tool-result-size-guard.sh +132 -0
- package/examples/tool-retry-budget-guard.sh +12 -0
- package/examples/transcript-contamination-detector.sh +138 -0
- package/examples/trustfall-mcp-injection-guard.sh +103 -0
- package/examples/ultrareview-large-diff-advisor.sh +184 -0
- package/examples/unbounded-output-guard.sh +94 -0
- package/examples/uncommitted-changes-stop.sh +1 -0
- package/examples/uncommitted-discard-guard.sh +23 -5
- package/examples/uncommitted-work-guard.sh +12 -0
- package/examples/usage-warn.sh +0 -0
- package/examples/user-account-guard.sh +12 -0
- package/examples/userprompt-submit-receipt.sh +123 -0
- package/examples/variable-expansion-guard.sh +12 -0
- package/examples/verify-after-publish-reminder.sh +93 -0
- package/examples/verify-before-commit.sh +12 -0
- package/examples/version-bump-detector.sh +156 -0
- package/examples/version-regression-warner.sh +144 -0
- package/examples/vue-lint-on-edit.sh +1 -0
- package/examples/warn-cron-cost-trap.sh +173 -0
- package/examples/webfetch-runaway-guard.sh +89 -0
- package/examples/wellness-break-reminder.sh +118 -0
- package/examples/windows-destructive-command-guard.sh +177 -0
- package/examples/windows-path-guard.sh +12 -0
- package/examples/windows-python-stub-detector.sh +63 -0
- package/examples/work-hours-guard.sh +12 -0
- package/examples/working-directory-fence.sh +12 -0
- package/examples/workspace-lease-guard.sh +205 -0
- package/examples/worktree-create-log.sh +1 -0
- package/examples/worktree-delete-guard.sh +12 -0
- package/examples/worktree-edit-boundary-guard.sh +127 -0
- package/examples/worktree-escape-write-guard.sh +114 -0
- package/examples/worktree-hook-linker.sh +0 -0
- package/examples/worktree-hooks-path-fix.sh +111 -0
- package/examples/worktree-parent-write-guard.sh +43 -0
- package/examples/worktree-project-unify.sh +2 -1
- package/examples/worktree-remove-uncommitted-guard.sh +13 -0
- package/examples/worktree-unmerged-guard.sh +7 -1
- package/examples/write-byte-integrity-verifier.sh +190 -0
- package/examples/write-empty-content-guard.sh +67 -0
- package/examples/write-nul-corruption-detector.sh +61 -0
- package/examples/write-overwrite-confirm.sh +160 -14
- package/examples/write-secret-guard.sh +27 -5
- package/examples/write-shrink-guard.sh +12 -0
- package/examples/write-test-ratio.sh +0 -0
- package/examples/wsl-host-disk-space-guard.sh +97 -0
- package/examples/xml-format-leak-detector.sh +266 -0
- package/examples/yaml-syntax-check.sh +12 -0
- package/hooks/hooks.json +6 -6
- package/index.mjs +1699 -183
- package/mission.md +2 -0
- package/package.json +4 -4
- package/plugins/credential-guard/.claude-plugin/plugin.json +9 -7
- package/plugins/git-protection/.claude-plugin/plugin.json +10 -8
- package/plugins/safety-essentials/.claude-plugin/plugin.json +9 -7
- package/plugins/token-guard/.claude-plugin/plugin.json +10 -8
- package/scripts/agents-md-sync-setup.sh +156 -0
- package/scripts/autonomy-blocked-summary.sh +148 -0
- package/scripts/build-search-index.py +43 -0
- package/scripts/build-sitemap.py +119 -0
- package/scripts/cc-doctor.sh +192 -0
- package/scripts/check-hook-event-names.py +127 -0
- package/scripts/check-misfire-instrument.sh +64 -0
- package/scripts/claim-verify-audit.sh +467 -0
- package/scripts/cowork-claudemd-helper.sh +136 -0
- package/scripts/june-15-deprecated-model-scan.sh +111 -0
- package/scripts/measure-heredoc-shapes.sh +67 -0
- package/scripts/measure-literal-match-misfire.sh +110 -0
- package/scripts/probe-scope-guard-branches.sh +48 -0
- package/scripts/probe-skip-line-both-ways.sh +65 -0
- package/scripts/receipts-aggregate.py +199 -0
- package/scripts/session-forensic-audit.py +360 -0
- package/scripts.json +9 -9
- package/scripts.json.bak-2026-07-27-find +13 -0
- package/skills/safety-setup/SKILL.md +5 -5
- package/tests/approve-side-remaining-two.test.sh +129 -0
- package/tests/approver-list-granularity.test.sh +145 -0
- package/tests/askuserquestion-autonomy-gate.test.sh +181 -0
- package/tests/audit-ci-gate.test.sh +87 -0
- package/tests/audit-cross-layer-claudemd.test.sh +170 -0
- package/tests/audit-fail-open-parse.test.sh +100 -0
- package/tests/auto-approve-compound-tail.test.sh +194 -0
- package/tests/auto-mode-path-invoked-commands.test.sh +89 -0
- package/tests/auto-mode-quoted-targets.test.sh +127 -0
- package/tests/auto-mode-unquoted-targets.test.sh +112 -0
- package/tests/bash-secret-output-detector-detects.test.sh +102 -0
- package/tests/blindspots-cross-layer.test.sh +177 -0
- package/tests/block-database-wipe.test.sh +64 -0
- package/tests/bundled-short-flags-bypass.test.sh +85 -0
- package/tests/cd-git-allow-compound-tail.test.sh +67 -0
- package/tests/chown-guard-filesystem-root.test.sh +64 -0
- package/tests/ci-workflow-guard-skip-rule.test.sh +115 -0
- package/tests/compound-deny-safe-rm-targets.test.sh +105 -0
- package/tests/core-scripts-parser-fallback.test.sh +140 -0
- package/tests/destructive-guard-bare-glob.test.sh +74 -0
- package/tests/destructive-guard-every-operand.test.sh +100 -0
- package/tests/destructive-guard-find-deletion.test.sh +114 -0
- package/tests/destructive-guard-flag-order.test.sh +106 -0
- package/tests/destructive-guard-mentions-vs-invocations.test.sh +107 -0
- package/tests/destructive-guard-quoted-target.test.sh +89 -0
- package/tests/destructive-guard-separators.test.sh +105 -0
- package/tests/destructive-guard-variable-target.test.sh +98 -0
- package/tests/destructive-guard-wrapped-command.test.sh +91 -0
- package/tests/doctor-hook-disabling-env.test.sh +92 -0
- package/tests/doctor-misspelled-settings-keys.test.sh +106 -0
- package/tests/example-guards-wrapped-command.test.sh +169 -0
- package/tests/file-edit-backup.test.sh +93 -0
- package/tests/git-filter-repo-guard.test.sh +60 -0
- package/tests/git-global-options-bypass.test.sh +141 -0
- package/tests/git-invocation-prefixes-all-guards.test.sh +114 -0
- package/tests/git-maintenance-guard.test.sh +83 -0
- package/tests/git-pack-temp-cleanup-guard.test.sh +133 -0
- package/tests/git-rm-orphan-wipe-guard.test.sh +66 -0
- package/tests/git-submodule-guard.test.sh +50 -0
- package/tests/grep-pcre-portability.test.sh +155 -0
- package/tests/hook-registration-matches-input.test.sh +73 -0
- package/tests/hook-trigger-matches-envelope.test.sh +178 -0
- package/tests/install-does-not-claim-protection.test.sh +110 -0
- package/tests/install-example-standalone-tools.test.sh +139 -0
- package/tests/line-continuation-bypass.test.sh +114 -0
- package/tests/mcp-config-poisoning-audit.test.sh +106 -0
- package/tests/nested-background-agent-guard.test.sh +58 -0
- package/tests/no-unqualified-safety-claims.test.sh +114 -0
- package/tests/option-eating-grep-patterns.test.sh +130 -0
- package/tests/outdated-core-guards.test.sh +134 -0
- package/tests/outdated-report.test.sh +155 -0
- package/tests/output-secret-mask-warns.test.sh +73 -0
- package/tests/plugin-hooks-fail-open-under-sh.test.sh +165 -0
- package/tests/plugins-word-order.test.sh +126 -0
- package/tests/powershell-remove-item-guard.test.sh +85 -0
- package/tests/project-dir-naming.test.sh +103 -0
- package/tests/quoted-safe-targets-and-mentions.test.sh +190 -0
- package/tests/reroute-after-block-guard.test.sh +104 -0
- package/tests/secret-guard-documented-promises.test.sh +97 -0
- package/tests/session-plugin-pin-watch.test.sh +45 -0
- package/tests/settings-unreadable-refuses-to-write.test.sh +95 -0
- package/tests/shield-no-silent-adoption.test.py +110 -0
- package/tests/shield-no-silent-adoption.test.sh +46 -0
- package/tests/stop-transcript-write-health.test.sh +46 -0
- package/tests/system-dir-guard-root-erased.test.sh +66 -0
- package/tests/test-account-billing-log.sh +100 -0
- package/tests/test-account-routing-preflight.sh +77 -0
- package/tests/test-agent-sdk-credit-pool-monitor.sh +157 -0
- package/tests/test-agent-view-quota-warn.sh +184 -0
- package/tests/test-agents-md-edit-drift-warner.sh +176 -0
- package/tests/test-agents-md-loader.sh +204 -0
- package/tests/test-agents-md-sync-checker.sh +125 -0
- package/tests/test-ai-slop-punctuation-arrest.sh +280 -0
- package/tests/test-allowlist.sh +60 -0
- package/tests/test-always-allow-pattern-suggester.sh +147 -0
- package/tests/test-anthropic-base-url-guard.sh +88 -0
- package/tests/test-articulated-scope-capture.sh +139 -0
- package/tests/test-attachment-traversal-guard.sh +168 -0
- package/tests/test-aup-block-pattern-logger.sh +315 -0
- package/tests/test-aup-false-positive-helper.sh +188 -0
- package/tests/test-aup-large-tool-output-warner.sh +370 -0
- package/tests/test-aup-retry-loop-guard.sh +341 -0
- package/tests/test-auth-expiry-reminder.sh +303 -0
- package/tests/test-auth-macos-sleep-detector.sh +254 -0
- package/tests/test-auth-path-detector.sh +232 -0
- package/tests/test-auth-status-checker.sh +233 -0
- package/tests/test-authorized-reconfirmation-detector.sh +280 -0
- package/tests/test-background-cost-launch-guard.sh +62 -0
- package/tests/test-bash-allowlist-secondary-check.sh +143 -0
- package/tests/test-bash-fanout-bounded-rewriter.sh +186 -0
- package/tests/test-bash-project-fence.sh +127 -0
- package/tests/test-bg-permission-prompt-warner.sh +221 -0
- package/tests/test-binary-read-detector.sh +173 -0
- package/tests/test-broad-prefix-session-trap-warner.sh +167 -0
- package/tests/test-bulk-delete-target-resolution.sh +49 -0
- package/tests/test-bypass-mode-effective-verifier.sh +179 -0
- package/tests/test-cache-creation-drift-detector.sh +244 -0
- package/tests/test-cache-residue-detector.sh +429 -0
- package/tests/test-cache-tier-logger.sh +59 -0
- package/tests/test-cache-ttl-eviction-detector.sh +282 -0
- package/tests/test-cch-sentinel-precommit-guard.sh +64 -0
- package/tests/test-claim-verify-detector.sh +222 -0
- package/tests/test-claim-vs-caveat-checker.sh +134 -0
- package/tests/test-claude-code-version-pin-advisor.sh +353 -0
- package/tests/test-claude-md-reinjector.sh +173 -0
- package/tests/test-claude-md-size-monitor.sh +107 -0
- package/tests/test-claude-update-budget-guard.sh +132 -0
- package/tests/test-claude-update-smart.sh +91 -0
- package/tests/test-claudemd-tool-prohibition.sh +239 -0
- package/tests/test-cli-config-pinning-detector.sh +233 -0
- package/tests/test-cliff-countdown-advisor.sh +138 -0
- package/tests/test-closure-word-verify-gate.sh +158 -0
- package/tests/test-commit-all-scope-guard.sh +73 -0
- package/tests/test-commitment-carry-forward-arrest.sh +250 -0
- package/tests/test-compact-dispatch-watchdog.sh +147 -0
- package/tests/test-completion-claim-without-verification-detector.sh +326 -0
- package/tests/test-compound-bash-permission-resolver.sh +264 -0
- package/tests/test-compound-command-deny-enforcer.sh +67 -0
- package/tests/test-context-length-budget.sh +68 -0
- package/tests/test-context-usage-drift-alert.sh +52 -22
- package/tests/test-cost-incident-self-audit.sh +94 -0
- package/tests/test-cowork-claude-md-load-checker.sh +257 -0
- package/tests/test-cowork-claudemd-helper.sh +141 -0
- package/tests/test-cowork-fuse-staleness-watcher.sh +287 -0
- package/tests/test-cowork-hook-absence-warner.sh +230 -0
- package/tests/test-cowork-model-picker-advisor.sh +317 -0
- package/tests/test-credential-exfil-guard.sh +62 -0
- package/tests/test-cron-create-receipt.sh +165 -0
- package/tests/test-cross-product-mcp-spawn-detector.sh +112 -0
- package/tests/test-daemon-zombie-worker-surfacer.sh +71 -0
- package/tests/test-daily-cost-guard.sh +131 -0
- package/tests/test-deny-rule-integrity-verifier.sh +288 -0
- package/tests/test-deployment-readback-gate.sh +92 -0
- package/tests/test-deployment-readback-gh-adapter.sh +163 -0
- package/tests/test-disabled-feature-toggle-advisor.sh +78 -0
- package/tests/test-dispatch-allowlist-preflight.sh +385 -0
- package/tests/test-dispatch-liveness-watchdog.sh +319 -0
- package/tests/test-dispatch-receipt.sh +314 -0
- package/tests/test-dotenv-anthropic-key-billing-guard.sh +160 -0
- package/tests/test-echo-probe-spam-detector.sh +143 -0
- package/tests/test-edit-quote-ambiguity-guard.sh +75 -0
- package/tests/test-ephemeral-container-detector.sh +251 -0
- package/tests/test-evidence-claim-gate.sh +291 -0
- package/tests/test-extended-thinking-loop-guard.sh +289 -0
- package/tests/test-extended-thinking-resume-warning.sh +240 -0
- package/tests/test-extended-thinking-tool-use-mismatch-detector.sh +236 -0
- package/tests/test-fabricated-command-detector.sh +296 -0
- package/tests/test-false-disk-full-guard.sh +36 -0
- package/tests/test-feature-deprecation-detector.sh +117 -0
- package/tests/test-forbidden-response-phrase-detector.sh +246 -0
- package/tests/test-git-operations-require-approval.sh +53 -0
- package/tests/test-git-push-blast-radius-guard.sh +115 -0
- package/tests/test-goal-iteration-limit-warner.sh +128 -0
- package/tests/test-growthbook-flag-monitor.sh +428 -0
- package/tests/test-halt-signal-detector.sh +120 -0
- package/tests/test-hook-self-disable-detector.sh +232 -0
- package/tests/test-iteration-quality-degradation-detector.sh +244 -0
- package/tests/test-long-session-malformed-tool-call-detector.sh +185 -0
- package/tests/test-marketplace-plugins.sh +193 -0
- package/tests/test-mcp-misdiagnosis-arrest.sh +235 -0
- package/tests/test-mcp-orphan-leak-warner.sh +71 -0
- package/tests/test-mcp-permissions-ask-warner.sh +207 -0
- package/tests/test-mcp-routine-approval-detector.sh +229 -0
- package/tests/test-mcp-startup-bloat-detector.sh +141 -0
- package/tests/test-mcp-stdio-compatibility-test.sh +112 -0
- package/tests/test-memory-chain-audit.sh +59 -0
- package/tests/test-memory-orphan-detector.sh +227 -0
- package/tests/test-model-swap-suggester.sh +368 -0
- package/tests/test-model-version-lock.sh +83 -0
- package/tests/test-multi-file-plan-routing-gate.sh +277 -0
- package/tests/test-multi-window-auth-drift-detector.sh +262 -0
- package/tests/test-nested-spawn-inflight-guard.sh +281 -0
- package/tests/test-no-force-flag.sh +49 -0
- package/tests/test-non-english-quality-warner.sh +229 -0
- package/tests/test-oauth-refresh-monitor.sh +311 -0
- package/tests/test-opus-degradation-tracker.sh +274 -0
- package/tests/test-opus48-routine-task-warning.sh +201 -0
- package/tests/test-opus48-thinking-wedge-advisor.sh +249 -0
- package/tests/test-output-token-spike-detector.sh +315 -0
- package/tests/test-parallel-batch-size-limiter.sh +228 -0
- package/tests/test-parallel-cascade-detector.sh +191 -0
- package/tests/test-partial-view-claim-arrest.sh +272 -0
- package/tests/test-per-prompt-token-cap.sh +136 -0
- package/tests/test-persisted-1m-model-advisor.sh +71 -0
- package/tests/test-plugin-hooks-json-bloat-detector.sh +267 -0
- package/tests/test-post-edit-disk-verify.sh +294 -0
- package/tests/test-pre-bash-sed-line-ending-windows.sh +108 -0
- package/tests/test-pre-execution-claim-detector.sh +366 -0
- package/tests/test-private-key-backup-and-git-credentials.sh +100 -0
- package/tests/test-proxy-capture-suggester.sh +214 -0
- package/tests/test-public-artefact-socratic-narrowing.sh +346 -0
- package/tests/test-quota-anomaly-detector.sh +321 -0
- package/tests/test-quota-reset-audit.sh +81 -0
- package/tests/test-read-loop-detector.sh +137 -0
- package/tests/test-read-once-guard.sh +85 -0
- package/tests/test-receipts-aggregate.sh +143 -0
- package/tests/test-redirect-fragment-warner.sh +130 -0
- package/tests/test-redundant-read-blocker.sh +155 -0
- package/tests/test-refusal-arrest-gate.sh +303 -0
- package/tests/test-remote-control-billing-classifier.sh +125 -0
- package/tests/test-resume-drift-watcher.sh +65 -0
- package/tests/test-rg-replace-flag-detector.sh +175 -0
- package/tests/test-rhetorical-verification-prompt-detector.sh +237 -0
- package/tests/test-rm-safety-net.sh +115 -0
- package/tests/test-route-handler-emptiness-gate.sh +300 -0
- package/tests/test-runtime-binary-change-detector.sh +196 -0
- package/tests/test-same-command-repeat-detector.sh +165 -0
- package/tests/test-same-correction-arrest.sh +165 -0
- package/tests/test-scope-expansion-receipt.sh +207 -0
- package/tests/test-server-side-prompt-injection-detector.sh +181 -0
- package/tests/test-session-persistence-verifier.sh +128 -0
- package/tests/test-session-rate-monitor.sh +284 -0
- package/tests/test-session-start-quota-status.sh +210 -0
- package/tests/test-session-start-safety-check.sh +138 -0
- package/tests/test-settings-hooks-key-restorer.sh +257 -0
- package/tests/test-settings-json-health-check.sh +70 -0
- package/tests/test-settings-regression-tester.sh +197 -0
- package/tests/test-skill-cumulative-size-detector.sh +198 -0
- package/tests/test-skill-description-drop-detector.sh +236 -0
- package/tests/test-skill-truncation-detector.sh +263 -0
- package/tests/test-skills-context-recorder.sh +329 -0
- package/tests/test-skills-load-verifier.sh +184 -0
- package/tests/test-skills-settings-validator.sh +242 -0
- package/tests/test-sonnet-45-deprecation-helper.sh +150 -0
- package/tests/test-spurious-malformed-notice-detector.sh +290 -0
- package/tests/test-sql-bulk-delete-warn.sh +123 -0
- package/tests/test-ssh-key-protect.sh +81 -0
- package/tests/test-stale-temp-settings-detector.sh +161 -0
- package/tests/test-standing-rule-session-surfacer.sh +215 -0
- package/tests/test-starter-hooks-manifest.sh +96 -0
- package/tests/test-stop-hook-sigterm-wrapper.sh +258 -0
- package/tests/test-strict-allowlist.sh +72 -0
- package/tests/test-subagent-boundary-precheck.sh +137 -0
- package/tests/test-subagent-closure-verify-gate.sh +193 -0
- package/tests/test-subagent-destructive-git-guard.sh +86 -0
- package/tests/test-subagent-identity-leak-guard.sh +62 -0
- package/tests/test-subagent-identity-reassertion.sh +61 -0
- package/tests/test-subagent-inheritance-tester.sh +319 -0
- package/tests/test-subagent-permission-mode-guard.sh +61 -0
- package/tests/test-subagent-spawn-verification-enforcer.sh +60 -0
- package/tests/test-subagent-tool-allowlist-enforcer.sh +62 -0
- package/tests/test-subagent-tool-call-limiter.sh +97 -0
- package/tests/test-subscription-api-billing-warner.sh +138 -0
- package/tests/test-subscription-bypass-detector.sh +255 -0
- package/tests/test-temporal-suggestion-detector.sh +183 -0
- package/tests/test-thinking-budget-effort-mismatch-detector.sh +327 -0
- package/tests/test-tokenizer-ratio-alert-corpus.sh +77 -0
- package/tests/test-tokenizer-ratio-alert.sh +93 -0
- package/tests/test-tool-result-correlation-checker.sh +264 -0
- package/tests/test-tool-result-size-guard.sh +121 -0
- package/tests/test-transcript-contamination-detector.sh +264 -0
- package/tests/test-trigger-header-parsing.sh +151 -0
- package/tests/test-ultrareview-large-diff-advisor.sh +192 -0
- package/tests/test-userprompt-submit-receipt.sh +181 -0
- package/tests/test-verify-after-publish-reminder.sh +184 -0
- package/tests/test-version-bump-detector.sh +212 -0
- package/tests/test-version-regression-warner.sh +165 -0
- package/tests/test-warn-cron-cost-trap.sh +82 -0
- package/tests/test-webfetch-runaway-guard.sh +77 -0
- package/tests/test-wellness-break-reminder.sh +138 -0
- package/tests/test-windows-destructive-command-guard.sh +169 -0
- package/tests/test-windows-python-stub-detector.sh +146 -0
- package/tests/test-worktree-edit-boundary-guard.sh +219 -0
- package/tests/test-write-byte-integrity-verifier.sh +192 -0
- package/tests/test-xml-format-leak-detector.sh +299 -0
- package/tests/trustfall-mcp-injection-guard.test.sh +183 -0
- package/tests/workspace-lease-guard.test.sh +144 -0
- package/tests/worktree-escape-write-guard.test.sh +68 -0
- package/tests/worktree-hooks-path-fix.test.sh +181 -0
- package/tests/worktree-parent-write-guard.test.sh +51 -0
- package/tests/write-empty-content-guard.test.sh +39 -0
- package/tests/write-nul-corruption-detector.test.sh +29 -0
- package/tests/write-overwrite-unread-content.test.sh +178 -0
- package/tests/wsl-host-disk-space-guard.test.sh +55 -0
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ================================================================
|
|
3
|
+
# bash-project-fence.sh — Block Bash commands that reach outside the project root
|
|
4
|
+
# ================================================================
|
|
5
|
+
# PURPOSE:
|
|
6
|
+
# Prevents Claude Code from reading, writing, or scanning files
|
|
7
|
+
# outside CLAUDE_PROJECT_DIR via Bash commands. The complement to
|
|
8
|
+
# working-directory-fence.sh (which covers Read/Edit/Write tools).
|
|
9
|
+
# Without this hook, CLAUDE.md restrictions on path scope are
|
|
10
|
+
# model-side soft constraints that the model can ignore.
|
|
11
|
+
#
|
|
12
|
+
# SOLVES Issue #56739: model ran `find` across the entire Desktop,
|
|
13
|
+
# located a personal file, and sent it to a 3rd-party API without
|
|
14
|
+
# user confirmation. CLAUDE.md had a project-directory restriction
|
|
15
|
+
# that the model ignored. Tool-layer enforcement was absent.
|
|
16
|
+
#
|
|
17
|
+
# TRIGGER: PreToolUse
|
|
18
|
+
# MATCHER: "Bash"
|
|
19
|
+
#
|
|
20
|
+
# HOW IT WORKS:
|
|
21
|
+
# Parses the Bash command for absolute path arguments. For each
|
|
22
|
+
# absolute path, resolves it against CLAUDE_PROJECT_DIR (or CWD as
|
|
23
|
+
# fallback). If any path resolves outside the project tree, blocks
|
|
24
|
+
# with exit 2 and a structured explanation.
|
|
25
|
+
#
|
|
26
|
+
# CONFIGURATION:
|
|
27
|
+
# CC_BASH_FENCE_ALLOW — colon-separated additional allowed prefixes
|
|
28
|
+
# (e.g., "/tmp:/var/log:/home/user/.config")
|
|
29
|
+
# Default: /tmp, /var/tmp, /dev/null, /dev/stdin, /dev/stdout, /dev/stderr
|
|
30
|
+
# CC_BASH_FENCE_ACTION — "block" (default) or "warn"
|
|
31
|
+
# CC_BASH_FENCE_OFF — set to "1" to disable the hook entirely
|
|
32
|
+
#
|
|
33
|
+
# WHAT IT DOES NOT DO:
|
|
34
|
+
# Does not parse arbitrary shell syntax (pipes, subshells, command
|
|
35
|
+
# substitution). For most cases this is sufficient — the model's
|
|
36
|
+
# surface use of `find`, `cat`, `grep`, `cp`, `mv`, `head`, `tail`,
|
|
37
|
+
# `ls` against absolute paths is what reaches outside the project.
|
|
38
|
+
# Operators who need stricter parsing should add a separate hook.
|
|
39
|
+
# ================================================================
|
|
40
|
+
|
|
41
|
+
set -u
|
|
42
|
+
|
|
43
|
+
# Honor disable flag
|
|
44
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
45
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
46
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
47
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
48
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
49
|
+
_nojq_warned="/tmp/cc-nojq-warned-bash-project-fence-$PPID"
|
|
50
|
+
[ -f "$_nojq_warned" ] || {
|
|
51
|
+
echo "WARNING [bash-project-fence]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
52
|
+
: > "$_nojq_warned"
|
|
53
|
+
}
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
if [ "${CC_BASH_FENCE_OFF:-0}" = "1" ]; then
|
|
57
|
+
exit 0
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
INPUT=$(cat)
|
|
61
|
+
COMMAND=$(printf '%s' "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
62
|
+
|
|
63
|
+
if [ -z "$COMMAND" ]; then
|
|
64
|
+
exit 0
|
|
65
|
+
fi
|
|
66
|
+
|
|
67
|
+
# Determine project root
|
|
68
|
+
PROJECT_ROOT="${CLAUDE_PROJECT_DIR:-$(pwd)}"
|
|
69
|
+
PROJECT_ROOT=$(realpath -m "$PROJECT_ROOT" 2>/dev/null || printf '%s' "$PROJECT_ROOT")
|
|
70
|
+
|
|
71
|
+
# Default allowed prefixes (system paths the model legitimately needs)
|
|
72
|
+
DEFAULT_ALLOW="/tmp:/var/tmp:/dev/null:/dev/stdin:/dev/stdout:/dev/stderr:/proc"
|
|
73
|
+
|
|
74
|
+
# Build allow list
|
|
75
|
+
ALLOW_PREFIXES="${PROJECT_ROOT}:${DEFAULT_ALLOW}"
|
|
76
|
+
if [ -n "${CC_BASH_FENCE_ALLOW:-}" ]; then
|
|
77
|
+
ALLOW_PREFIXES="${ALLOW_PREFIXES}:${CC_BASH_FENCE_ALLOW}"
|
|
78
|
+
fi
|
|
79
|
+
|
|
80
|
+
ACTION="${CC_BASH_FENCE_ACTION:-block}"
|
|
81
|
+
|
|
82
|
+
# Extract absolute path arguments from the command.
|
|
83
|
+
# Match tokens that start with / or ~/, but exclude pure flags (-x), URLs, and
|
|
84
|
+
# path-like substrings inside quoted JSON / env var assignments. We use a simple
|
|
85
|
+
# tokenizer based on shell word splitting; this misses some edge cases but
|
|
86
|
+
# covers the common file-access surface.
|
|
87
|
+
#
|
|
88
|
+
# Tokens captured:
|
|
89
|
+
# - /absolute/path
|
|
90
|
+
# - ~/home/path (expanded to $HOME)
|
|
91
|
+
# Tokens skipped:
|
|
92
|
+
# - flags starting with -
|
|
93
|
+
# - URLs (contain ://)
|
|
94
|
+
# - things that look like options for find: -path X, -name X (handled below)
|
|
95
|
+
|
|
96
|
+
declare -a OUTSIDE_PATHS=()
|
|
97
|
+
|
|
98
|
+
# Use a portable word-split. Word-split the command on whitespace and pipes;
|
|
99
|
+
# preserve quoted segments roughly by stripping quotes after split.
|
|
100
|
+
# shellcheck disable=SC2086
|
|
101
|
+
set -f
|
|
102
|
+
IFS=$' \t\n|;&'
|
|
103
|
+
for tok in $COMMAND; do
|
|
104
|
+
# Strip surrounding quotes
|
|
105
|
+
tok="${tok#\"}"; tok="${tok%\"}"
|
|
106
|
+
tok="${tok#\'}"; tok="${tok%\'}"
|
|
107
|
+
|
|
108
|
+
# Strip the punctuation that wraps a command, so a path inside a
|
|
109
|
+
# substitution or a subshell is still seen as a path. The word split above
|
|
110
|
+
# does not break on ( ) or a backtick, so `[[ -n $(ls ~/secrets) ]]` used to
|
|
111
|
+
# produce the token "~/secrets)", which matches neither the ~/ case nor the
|
|
112
|
+
# absolute-path case below, and the reference left the fence unnoticed.
|
|
113
|
+
# Measured 2026-08-04: the bare form was blocked and the wrapped form passed.
|
|
114
|
+
tok="${tok#\$(}"; tok="${tok#(}"; tok="${tok#\`}"
|
|
115
|
+
tok="${tok%)}"; tok="${tok%\`}"
|
|
116
|
+
|
|
117
|
+
# Expand ~/ to $HOME
|
|
118
|
+
case "$tok" in
|
|
119
|
+
'~'/*) tok="${HOME}${tok#\~}" ;;
|
|
120
|
+
'~') tok="${HOME}" ;;
|
|
121
|
+
esac
|
|
122
|
+
|
|
123
|
+
# Only check tokens that look like absolute paths
|
|
124
|
+
case "$tok" in
|
|
125
|
+
/*) ;; # absolute path - check it
|
|
126
|
+
*) continue ;;
|
|
127
|
+
esac
|
|
128
|
+
|
|
129
|
+
# Skip URLs (e.g., /http://... would be invalid anyway)
|
|
130
|
+
case "$tok" in
|
|
131
|
+
*://*) continue ;;
|
|
132
|
+
esac
|
|
133
|
+
|
|
134
|
+
# Resolve symlinks / .. against the filesystem (use -m for nonexistent paths)
|
|
135
|
+
RESOLVED=$(realpath -m "$tok" 2>/dev/null || printf '%s' "$tok")
|
|
136
|
+
|
|
137
|
+
# Check against each allowed prefix
|
|
138
|
+
ALLOWED=0
|
|
139
|
+
OLD_IFS="$IFS"
|
|
140
|
+
IFS=':'
|
|
141
|
+
for prefix in $ALLOW_PREFIXES; do
|
|
142
|
+
IFS="$OLD_IFS"
|
|
143
|
+
[ -z "$prefix" ] && continue
|
|
144
|
+
# Normalize prefix
|
|
145
|
+
prefix_norm=$(realpath -m "$prefix" 2>/dev/null || printf '%s' "$prefix")
|
|
146
|
+
# Match if RESOLVED equals prefix or starts with prefix + "/"
|
|
147
|
+
case "$RESOLVED" in
|
|
148
|
+
"$prefix_norm"|"$prefix_norm"/*)
|
|
149
|
+
ALLOWED=1
|
|
150
|
+
break
|
|
151
|
+
;;
|
|
152
|
+
esac
|
|
153
|
+
IFS=':'
|
|
154
|
+
done
|
|
155
|
+
IFS="$OLD_IFS"
|
|
156
|
+
|
|
157
|
+
if [ "$ALLOWED" -eq 0 ]; then
|
|
158
|
+
OUTSIDE_PATHS+=("$RESOLVED")
|
|
159
|
+
fi
|
|
160
|
+
done
|
|
161
|
+
set +f
|
|
162
|
+
|
|
163
|
+
if [ "${#OUTSIDE_PATHS[@]}" -eq 0 ]; then
|
|
164
|
+
exit 0
|
|
165
|
+
fi
|
|
166
|
+
|
|
167
|
+
# Report
|
|
168
|
+
{
|
|
169
|
+
if [ "$ACTION" = "warn" ]; then
|
|
170
|
+
echo "WARN: Bash command references path outside the project root."
|
|
171
|
+
else
|
|
172
|
+
echo "BLOCKED: Bash command references path outside the project root."
|
|
173
|
+
fi
|
|
174
|
+
echo " Project root: $PROJECT_ROOT"
|
|
175
|
+
for p in "${OUTSIDE_PATHS[@]}"; do
|
|
176
|
+
echo " Outside path: $p"
|
|
177
|
+
done
|
|
178
|
+
echo " Command head: $(printf '%s' "$COMMAND" | head -c 120)"
|
|
179
|
+
echo
|
|
180
|
+
echo " This hook enforces a project-root allow list at the Bash layer."
|
|
181
|
+
echo " Background: model-side restrictions (CLAUDE.md, system prompt) can"
|
|
182
|
+
echo " be ignored. See https://github.com/anthropics/claude-code/issues/56739."
|
|
183
|
+
echo
|
|
184
|
+
echo " To allow specific paths outside the project, set:"
|
|
185
|
+
echo " CC_BASH_FENCE_ALLOW=\"/path/one:/path/two\""
|
|
186
|
+
echo " To downgrade to a warning, set CC_BASH_FENCE_ACTION=warn."
|
|
187
|
+
echo " To disable entirely, set CC_BASH_FENCE_OFF=1."
|
|
188
|
+
} >&2
|
|
189
|
+
|
|
190
|
+
if [ "$ACTION" = "warn" ]; then
|
|
191
|
+
exit 0
|
|
192
|
+
fi
|
|
193
|
+
|
|
194
|
+
exit 2
|
|
@@ -14,6 +14,18 @@
|
|
|
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-bash-safety-auto-deny-$PPID"
|
|
23
|
+
[ -f "$_nojq_warned" ] || {
|
|
24
|
+
echo "WARNING [bash-safety-auto-deny]: 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
|
|
@@ -7,11 +7,37 @@
|
|
|
7
7
|
#
|
|
8
8
|
# How it works: PostToolUse hook on Bash that checks command stdout for
|
|
9
9
|
# patterns matching API keys, tokens, passwords, and connection strings.
|
|
10
|
-
#
|
|
10
|
+
# When one matches, it prints a warning on stderr, so you see it in the
|
|
11
|
+
# terminal. By default it does not interrupt the turn (exit 0).
|
|
12
|
+
#
|
|
13
|
+
# WHAT THIS DOES NOT DO BY DEFAULT: it does not put the warning in front of
|
|
14
|
+
# the model. Until 2026-09-20 this hook wrote {"systemMessage": ...} to
|
|
15
|
+
# stdout on exit 0 and the header said it warned the model. Measured on
|
|
16
|
+
# 2.1.278, PostToolUse matcher Bash, in a disposable HOME, judging by
|
|
17
|
+
# whether a unique token in the message came back when the model was asked
|
|
18
|
+
# to quote everything it had been shown:
|
|
19
|
+
#
|
|
20
|
+
# nothing printed (control) not delivered
|
|
21
|
+
# top-level {"systemMessage": ...}, exit 0 not delivered
|
|
22
|
+
# stderr + exit 2 (positive control) DELIVERED
|
|
23
|
+
#
|
|
24
|
+
# The positive control is the point: the probe can see a delivered message,
|
|
25
|
+
# so the middle row is not an artefact of how it was read. In that run the
|
|
26
|
+
# model said in as many words that no hook output appeared, while quoting
|
|
27
|
+
# the system reminders it had been given.
|
|
28
|
+
#
|
|
29
|
+
# So on exit 0 the warning reaches you and not the model. If you want the
|
|
30
|
+
# model to be told, set CC_SECRET_OUTPUT_BLOCK=1 below — that is the shape
|
|
31
|
+
# measured as delivered. It is a blocking error: the tool has already run,
|
|
32
|
+
# and Claude is told about it and can act on it.
|
|
11
33
|
#
|
|
12
34
|
# TRIGGER: PostToolUse
|
|
13
35
|
# MATCHER: "Bash"
|
|
14
36
|
#
|
|
37
|
+
# Environment:
|
|
38
|
+
# CC_SECRET_OUTPUT_BLOCK=1 — exit 2 after warning, so the model is told.
|
|
39
|
+
# Default (unset) warns on stderr and exits 0.
|
|
40
|
+
#
|
|
15
41
|
# Usage:
|
|
16
42
|
# {
|
|
17
43
|
# "hooks": {
|
|
@@ -46,7 +72,14 @@ if echo "$STDOUT" | grep -qiE '(mysql|postgres|mongodb|redis)://[^:]+:[^@]+@'; t
|
|
|
46
72
|
fi
|
|
47
73
|
|
|
48
74
|
# Private keys
|
|
49
|
-
|
|
75
|
+
# `--` is required: without it grep reads the leading dashes of the PEM
|
|
76
|
+
# header as options and dies with "unrecognized option", so this check
|
|
77
|
+
# silently never fired. The six existing checks in test.sh only assert
|
|
78
|
+
# exit 0, and this hook always exited 0, so they passed anyway.
|
|
79
|
+
# The same omission was found in ci-workflow-guard.sh and fixed in the same
|
|
80
|
+
# branch; a sweep of examples/ and hooks/ for a grep pattern starting with a
|
|
81
|
+
# dash found no third case.
|
|
82
|
+
if echo "$STDOUT" | grep -qE -- '-----BEGIN (RSA |EC |OPENSSH )?PRIVATE KEY-----'; then
|
|
50
83
|
FOUND="${FOUND}private key, "
|
|
51
84
|
fi
|
|
52
85
|
|
|
@@ -62,7 +95,15 @@ fi
|
|
|
62
95
|
|
|
63
96
|
if [ -n "$FOUND" ]; then
|
|
64
97
|
FOUND="${FOUND%, }"
|
|
65
|
-
|
|
98
|
+
# stderr, not stdout: a {"systemMessage": ...} object on stdout is dropped
|
|
99
|
+
# here (measured 2026-09-20, table in the header). stderr at least reaches
|
|
100
|
+
# the terminal, and with BLOCK=1 it reaches the model too.
|
|
101
|
+
echo "⚠ SECRET DETECTED in command output: ${FOUND}." >&2
|
|
102
|
+
echo " Do NOT repeat, log, or include these values in any output." >&2
|
|
103
|
+
echo " They are already in the context window and should be treated as redacted." >&2
|
|
104
|
+
if [ "${CC_SECRET_OUTPUT_BLOCK:-0}" = "1" ]; then
|
|
105
|
+
exit 2
|
|
106
|
+
fi
|
|
66
107
|
fi
|
|
67
108
|
|
|
68
109
|
exit 0
|
|
@@ -21,6 +21,18 @@
|
|
|
21
21
|
# }
|
|
22
22
|
# }
|
|
23
23
|
|
|
24
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
25
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
26
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
27
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
28
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
29
|
+
_nojq_warned="/tmp/cc-nojq-warned-bash-trace-guard-$PPID"
|
|
30
|
+
[ -f "$_nojq_warned" ] || {
|
|
31
|
+
echo "WARNING [bash-trace-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
32
|
+
: > "$_nojq_warned"
|
|
33
|
+
}
|
|
34
|
+
fi
|
|
35
|
+
|
|
24
36
|
INPUT=$(cat)
|
|
25
37
|
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
26
38
|
[ -z "$COMMAND" ] && exit 0
|
|
File without changes
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# bg-permission-prompt-warner.sh — Warn operators dispatching `claude --bg` that
|
|
3
|
+
# background sessions stall on permission prompts even under acceptEdits
|
|
4
|
+
# (Cluster 24 candidate, axis 24A — non-interactive permission gap)
|
|
5
|
+
#
|
|
6
|
+
# Background:
|
|
7
|
+
# Cluster 24 candidate axis 24A documents that `claude --bg` code-writing
|
|
8
|
+
# sessions stall on permission prompts even when invoked with
|
|
9
|
+
# `--permission-mode acceptEdits`. There is no non-interactive way to
|
|
10
|
+
# answer the prompt from the shell, so unattended automation that depends
|
|
11
|
+
# on `--bg` for fan-out blocks indefinitely on the first edit-permission
|
|
12
|
+
# gate.
|
|
13
|
+
#
|
|
14
|
+
# Anchor case:
|
|
15
|
+
# #64271 — `claude --bg` code-writing sessions stall on permission
|
|
16
|
+
# prompts with no non-interactive way to answer
|
|
17
|
+
#
|
|
18
|
+
# The structural shape: the operator dispatches a background session
|
|
19
|
+
# expecting it to run unattended, walks away, and returns to find the
|
|
20
|
+
# session paused indefinitely on a permission prompt that no automation
|
|
21
|
+
# layer can answer. The "background" framing implies the session can
|
|
22
|
+
# run without supervision; the permission gate breaks that expectation.
|
|
23
|
+
#
|
|
24
|
+
# Cluster 24 axes (4 sub-clusters):
|
|
25
|
+
# 24A — non-interactive permission gap (#64271, this hook)
|
|
26
|
+
# 24B — documentation gap: hook payload omits agent_id for bg sessions (#64272)
|
|
27
|
+
# 24C — resource-release gap: Windows daemon retains dir handle (#64273)
|
|
28
|
+
# 24D — result-delivery gap: iOS Dispatch / Advisor result not relayed
|
|
29
|
+
# (#64242, #64244, #64250)
|
|
30
|
+
#
|
|
31
|
+
# This hook is a SessionStart advisory that fires when:
|
|
32
|
+
# - the parent process command line contains `--bg` or `--background`
|
|
33
|
+
# (detected via /proc/$PPID/cmdline on Linux or `ps -o command` on
|
|
34
|
+
# macOS), AND
|
|
35
|
+
# - the operator has not already seen the advisory in this session
|
|
36
|
+
#
|
|
37
|
+
# The advisory describes the four sub-cluster axes, names the operator-side
|
|
38
|
+
# workaround for axis 24A (keep a terminal attached until the
|
|
39
|
+
# non-interactive path lands), and links the field guide.
|
|
40
|
+
#
|
|
41
|
+
# When this hook does NOT emit anything:
|
|
42
|
+
# - CC_BG_WARN_DISABLE=1
|
|
43
|
+
# - CC_BG_WARN_QUIET=1
|
|
44
|
+
# - the parent command line does not contain --bg / --background
|
|
45
|
+
# - the parent command line cannot be read
|
|
46
|
+
# - the advisory has already fired in this session
|
|
47
|
+
#
|
|
48
|
+
# Hook config (settings.json):
|
|
49
|
+
# {
|
|
50
|
+
# "hooks": {
|
|
51
|
+
# "SessionStart": [{
|
|
52
|
+
# "matcher": "",
|
|
53
|
+
# "hooks": [{ "type": "command", "command": "bash ~/.claude/hooks/bg-permission-prompt-warner.sh" }]
|
|
54
|
+
# }]
|
|
55
|
+
# }
|
|
56
|
+
# }
|
|
57
|
+
#
|
|
58
|
+
# Env vars:
|
|
59
|
+
# CC_BG_WARN_DISABLE=1 — never emit
|
|
60
|
+
# CC_BG_WARN_QUIET=1 — silent (process but never write to stderr)
|
|
61
|
+
# CC_BG_WARN_FORCE=1 — bypass parent-cmdline detection, always emit
|
|
62
|
+
# (tests, or for operators who want the
|
|
63
|
+
# advisory on every session-start)
|
|
64
|
+
# CC_BG_WARN_PARENT_CMD=<cmd> — parent command line override (tests)
|
|
65
|
+
# CC_BG_WARN_STATE_DIR=<path> — one-shot state dir override (default ~/.claude/state)
|
|
66
|
+
# CC_BG_WARN_SESSION_ID=<id> — session id override (tests)
|
|
67
|
+
#
|
|
68
|
+
# Design notes:
|
|
69
|
+
# - Opt-out. Operators who use --bg regularly and have already absorbed
|
|
70
|
+
# the limitation can disable. The default-on signal serves operators
|
|
71
|
+
# who are about to be surprised by the permission gate.
|
|
72
|
+
# - One-shot per session. The advisory fires once. Repeated firings
|
|
73
|
+
# across sessions of long-running --bg pilots add no signal.
|
|
74
|
+
# - Never blocks. Exit always 0. The advisory is informational.
|
|
75
|
+
# - Parent detection is best-effort: /proc on Linux, ps on macOS,
|
|
76
|
+
# fallback to env vars on platforms without either.
|
|
77
|
+
|
|
78
|
+
set -u
|
|
79
|
+
|
|
80
|
+
if [[ "${CC_BG_WARN_DISABLE:-0}" = "1" ]]; then
|
|
81
|
+
exit 0
|
|
82
|
+
fi
|
|
83
|
+
|
|
84
|
+
STATE_DIR="${CC_BG_WARN_STATE_DIR:-$HOME/.claude/state}"
|
|
85
|
+
mkdir -p "$STATE_DIR" 2>/dev/null
|
|
86
|
+
|
|
87
|
+
SESSION_ID="${CC_BG_WARN_SESSION_ID:-${CLAUDE_SESSION_ID:-default}}"
|
|
88
|
+
GUARD_FILE="$STATE_DIR/bg-warn-${SESSION_ID}.fired"
|
|
89
|
+
|
|
90
|
+
if [[ -f "$GUARD_FILE" ]]; then
|
|
91
|
+
exit 0
|
|
92
|
+
fi
|
|
93
|
+
|
|
94
|
+
# Detect parent command line. Order of attempts:
|
|
95
|
+
# 1) explicit override via env var (tests)
|
|
96
|
+
# 2) /proc/$PPID/cmdline (Linux)
|
|
97
|
+
# 3) ps -o command -p $PPID (macOS)
|
|
98
|
+
PARENT_CMD="${CC_BG_WARN_PARENT_CMD:-}"
|
|
99
|
+
if [[ -z "$PARENT_CMD" ]]; then
|
|
100
|
+
if [[ -r "/proc/$PPID/cmdline" ]]; then
|
|
101
|
+
# Replace NULs with spaces for grep
|
|
102
|
+
PARENT_CMD=$(tr '\0' ' ' < "/proc/$PPID/cmdline" 2>/dev/null)
|
|
103
|
+
elif command -v ps >/dev/null 2>&1; then
|
|
104
|
+
PARENT_CMD=$(ps -o command= -p "$PPID" 2>/dev/null)
|
|
105
|
+
fi
|
|
106
|
+
fi
|
|
107
|
+
|
|
108
|
+
# Decide whether to emit. CC_BG_WARN_FORCE bypasses parent-cmdline detection.
|
|
109
|
+
SHOULD_EMIT=0
|
|
110
|
+
if [[ "${CC_BG_WARN_FORCE:-0}" = "1" ]]; then
|
|
111
|
+
SHOULD_EMIT=1
|
|
112
|
+
elif [[ -n "$PARENT_CMD" ]] && echo "$PARENT_CMD" | grep -qE -- '(--bg|--background)\b'; then
|
|
113
|
+
SHOULD_EMIT=1
|
|
114
|
+
fi
|
|
115
|
+
|
|
116
|
+
if [[ "$SHOULD_EMIT" -ne 1 ]]; then
|
|
117
|
+
exit 0
|
|
118
|
+
fi
|
|
119
|
+
|
|
120
|
+
# Mark one-shot guard.
|
|
121
|
+
touch "$GUARD_FILE" 2>/dev/null
|
|
122
|
+
|
|
123
|
+
if [[ "${CC_BG_WARN_QUIET:-0}" = "1" ]]; then
|
|
124
|
+
exit 0
|
|
125
|
+
fi
|
|
126
|
+
|
|
127
|
+
cat >&2 <<EOF
|
|
128
|
+
|
|
129
|
+
────────────────────────────────────────────────────────────────────
|
|
130
|
+
Background dispatch advisory — Cluster 24 axis 24A (--bg permission gap)
|
|
131
|
+
────────────────────────────────────────────────────────────────────
|
|
132
|
+
Parent command line includes \`--bg\` / \`--background\`. This session
|
|
133
|
+
appears to be running as a background-dispatched Claude Code session.
|
|
134
|
+
|
|
135
|
+
The Cluster 24 axis 24A pattern: \`claude --bg\` code-writing sessions
|
|
136
|
+
stall on permission prompts even under \`--permission-mode acceptEdits\`.
|
|
137
|
+
There is no non-interactive way to answer the prompt from the shell,
|
|
138
|
+
so unattended automation that depends on --bg blocks indefinitely on
|
|
139
|
+
the first edit-permission gate.
|
|
140
|
+
|
|
141
|
+
Anchor case: #64271.
|
|
142
|
+
|
|
143
|
+
Recommended operator-side workaround until the non-interactive path
|
|
144
|
+
lands upstream:
|
|
145
|
+
|
|
146
|
+
1) Keep a terminal attached to the dispatcher process until the
|
|
147
|
+
background session completes — the permission prompts surface
|
|
148
|
+
there and can be answered manually.
|
|
149
|
+
2) For long-running unattended automation, do not rely on --bg
|
|
150
|
+
alone; combine with explicit non-interactive Bash invocations
|
|
151
|
+
that bypass the edit-permission surface entirely.
|
|
152
|
+
3) Audit your tool-call distribution. Tool calls that trigger
|
|
153
|
+
edit-permission gates (Write, Edit, NotebookEdit) are the ones
|
|
154
|
+
that stall; read-only tool calls (Read, Glob, Bash with safe
|
|
155
|
+
commands) do not.
|
|
156
|
+
|
|
157
|
+
Three sibling axes also documented in Cluster 24 candidate:
|
|
158
|
+
|
|
159
|
+
24B — \`hooks.md\` does not articulate that background-dispatched
|
|
160
|
+
sessions are top-level processes, so hook payloads omit
|
|
161
|
+
\`agent_id\` (#64272). Use \`session_id\` as the primary
|
|
162
|
+
correlator instead.
|
|
163
|
+
|
|
164
|
+
24C — On Windows, the background daemon retains directory handles
|
|
165
|
+
after \`claude rm\` (#64273). Sleep briefly or restart the
|
|
166
|
+
per-user node daemon before retrying directory deletion.
|
|
167
|
+
|
|
168
|
+
24D — Dispatch / iOS Dispatch / Advisor result-delivery surface
|
|
169
|
+
signals "completed" but the result never reaches the
|
|
170
|
+
orchestrator context (#64242, #64244, #64250). Verify with
|
|
171
|
+
an explicit completion-marker check rather than trusting
|
|
172
|
+
the UI signal.
|
|
173
|
+
|
|
174
|
+
Field guide: cluster-tracker.html on GitHub Pages, search "Cluster 24".
|
|
175
|
+
|
|
176
|
+
(This advisory fires once per session. To disable:
|
|
177
|
+
export CC_BG_WARN_DISABLE=1)
|
|
178
|
+
────────────────────────────────────────────────────────────────────
|
|
179
|
+
|
|
180
|
+
EOF
|
|
181
|
+
|
|
182
|
+
exit 0
|
|
@@ -14,6 +14,18 @@
|
|
|
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-bg-task-cooldown-guard-$PPID"
|
|
23
|
+
[ -f "$_nojq_warned" ] || {
|
|
24
|
+
echo "WARNING [bg-task-cooldown-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
|
TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
|
|
19
31
|
COOLDOWN="${CC_BG_COOLDOWN_SECS:-10}"
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ================================================================
|
|
3
|
+
# binary-read-detector.sh — Surface image / PDF / binary path
|
|
4
|
+
# references in user prompts before they reach the vision dispatch
|
|
5
|
+
# bus that bypasses PreToolUse hooks
|
|
6
|
+
# ================================================================
|
|
7
|
+
# PURPOSE:
|
|
8
|
+
# Issue #62639 documented that PreToolUse hooks do not fire when
|
|
9
|
+
# the Read tool reads image, PDF, or other binary files. The
|
|
10
|
+
# model receives the content via a vision-routing dispatch path
|
|
11
|
+
# that bypasses the hook bus entirely. Three related places
|
|
12
|
+
# exhibit the same gap:
|
|
13
|
+
#
|
|
14
|
+
# 1. Read on .png / .jpg / .webp / .gif / .heic — PreToolUse
|
|
15
|
+
# skipped, content goes straight to vision input
|
|
16
|
+
# 2. Read on .pdf — same skip; model receives parsed content
|
|
17
|
+
# but no hook event fires
|
|
18
|
+
# 3. Image attachments via `claude --image` or drag-and-drop
|
|
19
|
+
# in the desktop app — UserPromptSubmit fires but does not
|
|
20
|
+
# carry the image path in tool_input in a hook-readable
|
|
21
|
+
# schema
|
|
22
|
+
#
|
|
23
|
+
# This means PreToolUse cannot be a security boundary against
|
|
24
|
+
# prompt-injection-via-image attacks while the dispatch gap
|
|
25
|
+
# exists: an attacker who gets the model to Read a poisoned
|
|
26
|
+
# image bypasses every PreToolUse defense installed.
|
|
27
|
+
#
|
|
28
|
+
# The earliest hook surface that DOES fire for these cases is
|
|
29
|
+
# UserPromptSubmit. This hook scans the prompt text for binary
|
|
30
|
+
# path references and surfaces them to the operator with the
|
|
31
|
+
# articulated risk and operator-side options.
|
|
32
|
+
#
|
|
33
|
+
# WHO THIS PROTECTS:
|
|
34
|
+
# Operators relying on PreToolUse hooks to gate file access,
|
|
35
|
+
# especially those running Claude Code on machines where
|
|
36
|
+
# ~/Downloads/ or similar directories may contain untrusted
|
|
37
|
+
# image content (attachments from email, browser downloads).
|
|
38
|
+
#
|
|
39
|
+
# DETECTION:
|
|
40
|
+
# UserPromptSubmit. Scan the prompt for path-like substrings
|
|
41
|
+
# that end in a binary extension. Default extensions:
|
|
42
|
+
# png, jpg, jpeg, gif, webp, heic, pdf, mp4, mov, mp3, wav,
|
|
43
|
+
# zip, tar, gz, bin, exe, dll, so, dylib, doc, docx, xls,
|
|
44
|
+
# xlsx, ppt, pptx
|
|
45
|
+
# If matches found, emit an advisory naming the matched paths
|
|
46
|
+
# and articulating the bypass risk.
|
|
47
|
+
#
|
|
48
|
+
# OUTPUT:
|
|
49
|
+
# stderr advisory naming matched paths and articulating that:
|
|
50
|
+
# - PreToolUse hooks WILL NOT fire when these are Read
|
|
51
|
+
# - Hook-installed policies cannot be enforced against them
|
|
52
|
+
# - Operator should verify the content is trusted before
|
|
53
|
+
# proceeding (or pre-process to text out-of-band)
|
|
54
|
+
# Exit 0 always (advisory, not blocking) so the prompt still
|
|
55
|
+
# proceeds. The operator decides whether to continue.
|
|
56
|
+
#
|
|
57
|
+
# CONFIGURATION:
|
|
58
|
+
# CC_BINARY_READ_DISABLE — set to 1 to disable entirely
|
|
59
|
+
# CC_BINARY_READ_BLOCK — set to 1 to block (exit 2) instead
|
|
60
|
+
# of advisory pass-through
|
|
61
|
+
# CC_BINARY_READ_EXTENSIONS — colon-separated extension list
|
|
62
|
+
# override (without dots)
|
|
63
|
+
#
|
|
64
|
+
# RELATED ISSUES:
|
|
65
|
+
# https://github.com/anthropics/claude-code/issues/62639
|
|
66
|
+
#
|
|
67
|
+
# TRIGGER: UserPromptSubmit
|
|
68
|
+
# MATCHER: "" (all)
|
|
69
|
+
# ================================================================
|
|
70
|
+
|
|
71
|
+
set -u
|
|
72
|
+
|
|
73
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
74
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
75
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
76
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
77
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
78
|
+
_nojq_warned="/tmp/cc-nojq-warned-binary-read-detector-$PPID"
|
|
79
|
+
[ -f "$_nojq_warned" ] || {
|
|
80
|
+
echo "WARNING [binary-read-detector]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
81
|
+
: > "$_nojq_warned"
|
|
82
|
+
}
|
|
83
|
+
fi
|
|
84
|
+
|
|
85
|
+
INPUT=$(cat 2>/dev/null || echo "{}")
|
|
86
|
+
|
|
87
|
+
[ "${CC_BINARY_READ_DISABLE:-0}" = "1" ] && exit 0
|
|
88
|
+
|
|
89
|
+
DEFAULT_EXTS='png:jpg:jpeg:gif:webp:heic:pdf:mp4:mov:mp3:wav:zip:tar:gz:bin:exe:dll:so:dylib:doc:docx:xls:xlsx:ppt:pptx'
|
|
90
|
+
EXTS="${CC_BINARY_READ_EXTENSIONS:-$DEFAULT_EXTS}"
|
|
91
|
+
|
|
92
|
+
PROMPT=$(printf '%s' "$INPUT" | jq -r '.prompt // .user_message // empty' 2>/dev/null)
|
|
93
|
+
[ -z "$PROMPT" ] && exit 0
|
|
94
|
+
|
|
95
|
+
# Build extension alternation pattern: \.(png|jpg|jpeg|...)\b
|
|
96
|
+
EXT_ALT=$(printf '%s' "$EXTS" | tr ':' '|')
|
|
97
|
+
PATTERN="\\.($EXT_ALT)(\\s|\$|['\"]|/|\\)|,|\\.|;)"
|
|
98
|
+
|
|
99
|
+
# Find all matching path-like substrings.
|
|
100
|
+
MATCHES=$(printf '%s' "$PROMPT" | grep -oiE "[A-Za-z0-9_./~-]+\\.($EXT_ALT)" | sort -u | head -10)
|
|
101
|
+
|
|
102
|
+
[ -z "$MATCHES" ] && exit 0
|
|
103
|
+
|
|
104
|
+
MSG="Binary path reference detected in prompt — PreToolUse hooks will NOT fire when Claude reads these:
|
|
105
|
+
|
|
106
|
+
$(printf '%s' "$MATCHES" | sed 's/^/ - /')
|
|
107
|
+
|
|
108
|
+
Issue #62639 documented that the Read tool dispatches image, PDF, and other binary content through a vision-routing path that bypasses the PreToolUse hook bus. Operator-installed PreToolUse policies cannot block, redirect, or audit these reads.
|
|
109
|
+
|
|
110
|
+
What this means for your hook policy:
|
|
111
|
+
- Any 'block reads outside this directory' rule does not apply
|
|
112
|
+
- Any 'audit-log every file read' rule misses these
|
|
113
|
+
- Prompt-injection-via-image attacks bypass every PreToolUse defense
|
|
114
|
+
|
|
115
|
+
Operator-side options:
|
|
116
|
+
1. Verify the file is trusted before proceeding. If it came from email, browser download, or external chat, treat it as untrusted
|
|
117
|
+
2. Pre-process to text out-of-band (e.g., 'tesseract image.png out' or 'pdftotext file.pdf -') and reference the text file instead. Text reads DO fire PreToolUse
|
|
118
|
+
3. For audit trails, install a PostToolUse hook — PostToolUse fires for binary reads (with empty tool_response.content for images) so the read is at least recorded
|
|
119
|
+
4. For policy enforcement, the only reliable layer is the OS (macOS Quarantine, Linux AppArmor profile, FUSE wrapper). PreToolUse cannot be a security boundary against this dispatch path
|
|
120
|
+
|
|
121
|
+
To disable this advisory:
|
|
122
|
+
CC_BINARY_READ_DISABLE=1
|
|
123
|
+
|
|
124
|
+
To block instead of advise (exit 2 to prevent the prompt from running):
|
|
125
|
+
CC_BINARY_READ_BLOCK=1
|
|
126
|
+
|
|
127
|
+
Related: cc-safe-setup Cluster 1 (Sub-Agent Observability), hook-bus completeness sub-pattern."
|
|
128
|
+
|
|
129
|
+
echo "[binary-read-detector] $MSG" >&2
|
|
130
|
+
|
|
131
|
+
if [ "${CC_BINARY_READ_BLOCK:-0}" = "1" ]; then
|
|
132
|
+
exit 2
|
|
133
|
+
fi
|
|
134
|
+
|
|
135
|
+
exit 0
|
|
@@ -11,6 +11,18 @@
|
|
|
11
11
|
# TRIGGER: PreToolUse
|
|
12
12
|
# MATCHER: "Bash"
|
|
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-binary-upload-guard-$PPID"
|
|
20
|
+
[ -f "$_nojq_warned" ] || {
|
|
21
|
+
echo "WARNING [binary-upload-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
|
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
16
28
|
[ -z "$COMMAND" ] && exit 0
|