cc-safe-setup 29.7.0 → 30.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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-circuit-breaker.sh +72 -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 +89 -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/thinking-stall-detector.sh +61 -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-circuit-breaker.sh +134 -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-exploration-budget-guard.sh +164 -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-thinking-stall-detector.sh +151 -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
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
-
# multiline-command-approver.sh — Auto-approve multiline commands
|
|
2
|
+
# multiline-command-approver.sh — Auto-approve multiline commands safely
|
|
3
3
|
#
|
|
4
4
|
# Solves: Auto-approve patterns fail on heredocs and multiline commands
|
|
5
5
|
# (#11932 — 47 reactions, 29 comments)
|
|
6
6
|
#
|
|
7
|
-
# How it works:
|
|
8
|
-
# 1. Extracts the first line of the command
|
|
9
|
-
# 2. Matches against a whitelist of safe command prefixes
|
|
10
|
-
# 3. If the first line is a safe command, auto-approves the entire command
|
|
11
|
-
#
|
|
12
7
|
# This is needed because Claude Code's built-in pattern matching
|
|
13
8
|
# evaluates the entire multiline string, which breaks on heredocs:
|
|
14
9
|
# echo 'commit message\n\nCo-Authored-By: ...' > file
|
|
@@ -26,15 +21,47 @@
|
|
|
26
21
|
# }]
|
|
27
22
|
# }
|
|
28
23
|
# }
|
|
24
|
+
#
|
|
25
|
+
# Rewritten 2026-08-03. The old version took `head -1` of the command and
|
|
26
|
+
# approved the whole thing when that one line matched a safe prefix. It had two
|
|
27
|
+
# holes, and the second one was the hook's own subject matter:
|
|
28
|
+
#
|
|
29
|
+
# separators : over the 32 commands it approved bare, appending
|
|
30
|
+
# `&& sudo rm -rf /var/app`, `; curl http://… | sh` or
|
|
31
|
+
# `&& git push --force` kept the approval 288/288 times.
|
|
32
|
+
# newlines : `cat <<'EOF' > note.txt` on line 1 with a destructive command
|
|
33
|
+
# on line 2 kept the approval 18/18 times. A hook whose entire
|
|
34
|
+
# purpose is multiline input was reading one line of it.
|
|
35
|
+
#
|
|
36
|
+
# The control says which repair this needs: the same dangerous commands on
|
|
37
|
+
# their own were approved 0/5 and 0/3 times. It never approved anything — it
|
|
38
|
+
# just never looked past the first line's first command.
|
|
39
|
+
#
|
|
40
|
+
# Reading further is not as simple as splitting on separators here, because the
|
|
41
|
+
# forms this hook exists to rescue put separators and newlines *inside* data:
|
|
42
|
+
# a commit message spanning lines, a heredoc body. So the command is scanned
|
|
43
|
+
# with the quoting state carried across lines, and heredoc bodies are skipped
|
|
44
|
+
# between their opener and their terminator. What is left is the actual command
|
|
45
|
+
# positions, and every one of them has to match a safe prefix.
|
|
46
|
+
#
|
|
47
|
+
# A line that does not qualify gets no decision, which leaves it to the normal
|
|
48
|
+
# permission flow. This hook only ever adds approval; it never blocks.
|
|
49
|
+
#
|
|
50
|
+
# Known limits:
|
|
51
|
+
# - Command substitution and backticks are refused outright. Their contents
|
|
52
|
+
# cannot be judged by reading the string.
|
|
53
|
+
# - Some prefixes below hand execution to an interpreter (`python3 -c`,
|
|
54
|
+
# `node -e`, `npx`, `curl -s`). Those are a separate problem from the one
|
|
55
|
+
# fixed here — the granularity of the safe list, not where it looks — and
|
|
56
|
+
# are measured separately.
|
|
57
|
+
# - More than one heredoc opened on the same line is refused rather than
|
|
58
|
+
# guessed at.
|
|
29
59
|
|
|
30
60
|
INPUT=$(cat)
|
|
31
61
|
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
32
62
|
[ -z "$COMMAND" ] && exit 0
|
|
33
63
|
|
|
34
|
-
#
|
|
35
|
-
FIRST_LINE=$(echo "$COMMAND" | head -1 | sed 's/^[[:space:]]*//')
|
|
36
|
-
|
|
37
|
-
# Safe command prefixes (first line only)
|
|
64
|
+
# Safe command prefixes. Each command position must match one of these.
|
|
38
65
|
SAFE_PREFIXES=(
|
|
39
66
|
"echo "
|
|
40
67
|
"printf "
|
|
@@ -71,19 +98,130 @@ SAFE_PREFIXES=(
|
|
|
71
98
|
"curl -s"
|
|
72
99
|
)
|
|
73
100
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
101
|
+
POSITIONS=()
|
|
102
|
+
|
|
103
|
+
cc_flush() {
|
|
104
|
+
local t="$1"
|
|
105
|
+
t="${t#"${t%%[![:space:]]*}"}"
|
|
106
|
+
t="${t%"${t##*[![:space:]]}"}"
|
|
107
|
+
[ -z "$t" ] && return 0
|
|
108
|
+
case "$t" in '#'*) return 0 ;; esac # a comment is not a command position
|
|
109
|
+
POSITIONS+=("$t")
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
# Split the command into command positions, carrying quoting state across lines
|
|
113
|
+
# and skipping heredoc bodies. Returns 1 for anything it will not vouch for.
|
|
114
|
+
cc_scan() {
|
|
115
|
+
local sq=0 dq=0 seg="" hd_active=0 hd_delim="" hd_dash=0
|
|
116
|
+
local line i n c nx j d q ch pending_delim="" pending_dash=0 pending_count=0
|
|
117
|
+
|
|
118
|
+
while IFS= read -r line; do
|
|
119
|
+
if [ "$hd_active" -eq 1 ]; then
|
|
120
|
+
local cand="$line"
|
|
121
|
+
[ "$hd_dash" -eq 1 ] && cand="${cand#"${cand%%[![:space:]]*}"}"
|
|
122
|
+
[ "$cand" = "$hd_delim" ] && hd_active=0
|
|
123
|
+
continue
|
|
124
|
+
fi
|
|
125
|
+
|
|
126
|
+
pending_delim=""; pending_count=0
|
|
127
|
+
i=0; n=${#line}
|
|
128
|
+
while [ "$i" -lt "$n" ]; do
|
|
129
|
+
c="${line:i:1}"
|
|
130
|
+
|
|
131
|
+
if [ "$sq" -eq 1 ]; then
|
|
132
|
+
[ "$c" = "'" ] && sq=0
|
|
133
|
+
seg+="$c"; i=$((i + 1)); continue
|
|
134
|
+
fi
|
|
135
|
+
if [ "$dq" -eq 1 ]; then
|
|
136
|
+
if [ "$c" = '\' ]; then seg+="${line:i:2}"; i=$((i + 2)); continue; fi
|
|
137
|
+
[ "$c" = '"' ] && dq=0
|
|
138
|
+
seg+="$c"; i=$((i + 1)); continue
|
|
139
|
+
fi
|
|
140
|
+
|
|
141
|
+
case "$c" in
|
|
142
|
+
"'") sq=1; seg+="$c"; i=$((i + 1)) ;;
|
|
143
|
+
'"') dq=1; seg+="$c"; i=$((i + 1)) ;;
|
|
144
|
+
'\') seg+="${line:i:2}"; i=$((i + 2)) ;;
|
|
145
|
+
'`') return 1 ;;
|
|
146
|
+
'$')
|
|
147
|
+
[ "${line:i+1:1}" = "(" ] && return 1
|
|
148
|
+
seg+="$c"; i=$((i + 1)) ;;
|
|
149
|
+
';'|'&'|'|')
|
|
150
|
+
cc_flush "$seg"; seg=""; i=$((i + 1)) ;;
|
|
151
|
+
'#')
|
|
152
|
+
# `#` opens a comment only at the start of a word
|
|
153
|
+
if [ -z "${seg//[[:space:]]/}" ] || [ "${line:i-1:1}" = " " ] || [ "${line:i-1:1}" = $'\t' ]; then
|
|
154
|
+
i="$n"
|
|
155
|
+
else
|
|
156
|
+
seg+="$c"; i=$((i + 1))
|
|
157
|
+
fi ;;
|
|
158
|
+
'<')
|
|
159
|
+
if [ "${line:i+1:1}" = "<" ]; then
|
|
160
|
+
j=$((i + 2)); d=""; q=""
|
|
161
|
+
if [ "${line:j:1}" = "-" ]; then pending_dash=1; j=$((j + 1)); else pending_dash=0; fi
|
|
162
|
+
while [ "${line:j:1}" = " " ] || [ "${line:j:1}" = $'\t' ]; do j=$((j + 1)); done
|
|
163
|
+
ch="${line:j:1}"
|
|
164
|
+
if [ "$ch" = "'" ] || [ "$ch" = '"' ]; then q="$ch"; j=$((j + 1)); fi
|
|
165
|
+
while [ "$j" -lt "$n" ]; do
|
|
166
|
+
ch="${line:j:1}"
|
|
167
|
+
if [ -n "$q" ]; then
|
|
168
|
+
if [ "$ch" = "$q" ]; then j=$((j + 1)); break; fi
|
|
169
|
+
else
|
|
170
|
+
case "$ch" in ' '|$'\t'|';'|'&'|'|'|'>'|'<') break ;; esac
|
|
171
|
+
fi
|
|
172
|
+
d+="$ch"; j=$((j + 1))
|
|
173
|
+
done
|
|
174
|
+
[ -z "$d" ] && return 1
|
|
175
|
+
pending_count=$((pending_count + 1))
|
|
176
|
+
[ "$pending_count" -gt 1 ] && return 1
|
|
177
|
+
pending_delim="$d"
|
|
178
|
+
seg+="<<"; i="$j"
|
|
179
|
+
else
|
|
180
|
+
seg+="$c"; i=$((i + 1))
|
|
181
|
+
fi ;;
|
|
182
|
+
*) seg+="$c"; i=$((i + 1)) ;;
|
|
183
|
+
esac
|
|
184
|
+
done
|
|
185
|
+
|
|
186
|
+
if [ "$sq" -eq 1 ] || [ "$dq" -eq 1 ]; then
|
|
187
|
+
# the newline is part of the string, not the end of a command
|
|
188
|
+
seg+=$'\n'
|
|
189
|
+
else
|
|
190
|
+
cc_flush "$seg"; seg=""
|
|
191
|
+
if [ -n "$pending_delim" ]; then
|
|
192
|
+
hd_delim="$pending_delim"; hd_dash="$pending_dash"; hd_active=1
|
|
193
|
+
fi
|
|
194
|
+
fi
|
|
195
|
+
done <<EOF
|
|
196
|
+
$COMMAND
|
|
197
|
+
EOF
|
|
198
|
+
|
|
199
|
+
# an unterminated quote means the string was not what it looked like
|
|
200
|
+
{ [ "$sq" -eq 1 ] || [ "$dq" -eq 1 ]; } && return 1
|
|
201
|
+
# an unterminated heredoc swallows the rest of the input as body. bash does
|
|
202
|
+
# treat it as data, so approving would not actually be wrong — but that
|
|
203
|
+
# rests on a subtlety, and refusing costs nothing.
|
|
204
|
+
[ "$hd_active" -eq 1 ] && return 1
|
|
205
|
+
cc_flush "$seg"
|
|
206
|
+
return 0
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
cc_scan || exit 0
|
|
210
|
+
[ "${#POSITIONS[@]}" -eq 0 ] && exit 0
|
|
211
|
+
|
|
212
|
+
for seg in "${POSITIONS[@]}"; do
|
|
213
|
+
matched=0
|
|
214
|
+
for prefix in "${SAFE_PREFIXES[@]}"; do
|
|
215
|
+
if [[ "$seg" == "$prefix"* ]]; then matched=1; break; fi
|
|
216
|
+
done
|
|
217
|
+
[ "$matched" -eq 1 ] || exit 0
|
|
86
218
|
done
|
|
87
219
|
|
|
88
|
-
|
|
220
|
+
jq -n '{
|
|
221
|
+
"hookSpecificOutput": {
|
|
222
|
+
"hookEventName": "PreToolUse",
|
|
223
|
+
"permissionDecision": "allow",
|
|
224
|
+
"permissionDecisionReason": "multiline-command-approver: every command position matches a safe prefix"
|
|
225
|
+
}
|
|
226
|
+
}'
|
|
89
227
|
exit 0
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# nested-background-agent-guard.sh — Refuse background agent spawns from inside a sub-agent
|
|
3
|
+
#
|
|
4
|
+
# Why: Issue #73829 (2026-07-04, desktop app, 0 comments when filed) is the canonical
|
|
5
|
+
# report. An intermediate background agent spawned *further* background agents
|
|
6
|
+
# instead of doing the sub-topics inline. A grandchild then re-invoked itself with
|
|
7
|
+
# filler no-ops ("checked current time", "Monitor timed out", "no-op while waiting")
|
|
8
|
+
# for 6.5 hours instead of quiescing. Once the intermediate agent's session ended,
|
|
9
|
+
# the top-level session had no handle on its descendants: TaskStop/TaskOutput
|
|
10
|
+
# returned "No task found" while the panel still showed them running. Several
|
|
11
|
+
# hundred USD burned, and restarting the app was the only way to clear it.
|
|
12
|
+
#
|
|
13
|
+
# The recursion only compounds because a *sub*-agent is allowed to spawn
|
|
14
|
+
# *background* agents at all. That is the one layer a client-side hook can gate
|
|
15
|
+
# deterministically, so that is what this hook does.
|
|
16
|
+
#
|
|
17
|
+
# ★2026-08-01: this got worse by default. Claude Code 2.1.219 changed nested subagent
|
|
18
|
+
# spawning from depth 1 to **depth 3 by default**:
|
|
19
|
+
#
|
|
20
|
+
# "Subagents can now spawn nested subagents up to depth 3 by default (was 1);
|
|
21
|
+
# set CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH=1 to disable nesting"
|
|
22
|
+
#
|
|
23
|
+
# Two consequences for anyone running unattended:
|
|
24
|
+
# - The blast radius of the #73829 shape tripled without anyone changing a setting.
|
|
25
|
+
# - Guards that cap the *number* of concurrent subagents do not see this at all.
|
|
26
|
+
# If each level spawns only a few, the count stays under the threshold while the
|
|
27
|
+
# depth keeps growing. Depth and width are different axes; this hook is the depth one.
|
|
28
|
+
#
|
|
29
|
+
# Why existing cc-safe-setup hooks miss this exact shape:
|
|
30
|
+
# - nested-spawn-inflight-guard.sh / max-subagent-count.sh / subagent-budget-guard.sh
|
|
31
|
+
# all bound how many subagents are in flight. None of them read whether the *current*
|
|
32
|
+
# run is itself a sub-agent, so none of them can tell depth 1 from depth 3.
|
|
33
|
+
# - background-cost-launch-guard.sh reads the Bash tool's run_in_background parameter.
|
|
34
|
+
# It never sees Agent/Task dispatches.
|
|
35
|
+
#
|
|
36
|
+
# What this does: on PreToolUse for Agent/Task/SendMessage, if run_in_background is true
|
|
37
|
+
# AND the current session is already a sub-agent (CLAUDE_CODE_CHILD_SESSION is set),
|
|
38
|
+
# it BLOCKS (exit 2). Foreground agents inside a sub-agent pass. Background agents from
|
|
39
|
+
# the top-level session pass. Only the nesting case is refused.
|
|
40
|
+
#
|
|
41
|
+
# Verified on 2026-07-04 against three inputs, and re-verified 2026-08-01 with the
|
|
42
|
+
# regression tests in tests/:
|
|
43
|
+
# (a) run_in_background:true + CLAUDE_CODE_CHILD_SESSION set -> exit 2 (blocked)
|
|
44
|
+
# (b) run_in_background:true + variable unset (top level) -> exit 0 (allowed)
|
|
45
|
+
# (c) foreground agent inside a sub-agent -> exit 0 (allowed)
|
|
46
|
+
#
|
|
47
|
+
# ★Limitation, stated plainly: CLAUDE_CODE_CHILD_SESSION is set inside spawned agent
|
|
48
|
+
# sessions on the CLI (confirmed while examining transcript inheritance in #73848).
|
|
49
|
+
# The desktop app was NOT confirmed to set it identically. Verify on your build first
|
|
50
|
+
# with a trivial printenv hook before relying on this.
|
|
51
|
+
#
|
|
52
|
+
# ★This does not recover already-orphaned tasks. They are app-managed tasks, not OS
|
|
53
|
+
# processes you can kill, and the spawning session is gone. The real fixes are
|
|
54
|
+
# provider-side: descendants should stay inspectable/stoppable from the root, and an
|
|
55
|
+
# agent awaiting children should quiesce rather than emit filler tool calls.
|
|
56
|
+
#
|
|
57
|
+
# Opt out: CC_NESTED_BG_AGENT_GUARD_DISABLE=1
|
|
58
|
+
#
|
|
59
|
+
# TRIGGER: PreToolUse MATCHER: "Agent|Task|SendMessage"
|
|
60
|
+
# settings.json:
|
|
61
|
+
# { "hooks": { "PreToolUse": [{ "matcher": "Agent|Task|SendMessage",
|
|
62
|
+
# "hooks": [{ "type": "command",
|
|
63
|
+
# "command": "~/.claude/hooks/nested-background-agent-guard.sh" }] }] } }
|
|
64
|
+
|
|
65
|
+
set -uo pipefail
|
|
66
|
+
|
|
67
|
+
[ "${CC_NESTED_BG_AGENT_GUARD_DISABLE:-0}" = "1" ] && exit 0
|
|
68
|
+
|
|
69
|
+
INPUT="$(cat)"
|
|
70
|
+
|
|
71
|
+
# jq が無い環境で黙って素通りしないこと。2026-07-27 に、配っていた17本が
|
|
72
|
+
# jq 不在で沈黙して素通りしていた(遮断すべき14通りが3環境すべてで0/14)。
|
|
73
|
+
# 「検査する対象が無かった」と「検査する道具が無かった」を混同しないため、
|
|
74
|
+
# ここでは通すが必ず声を出す。どれも無い環境で遮断を選ぶと全ツール呼び出しが
|
|
75
|
+
# 止まって Claude Code が使えなくなるので、fail-open + 警告にする。
|
|
76
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
77
|
+
echo "nested-background-agent-guard: jq not found — cannot inspect this dispatch, passing through unchecked." >&2
|
|
78
|
+
exit 0
|
|
79
|
+
fi
|
|
80
|
+
|
|
81
|
+
TOOL="$(printf '%s\n' "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)"
|
|
82
|
+
case "$TOOL" in
|
|
83
|
+
Agent|Task|SendMessage) ;;
|
|
84
|
+
*) exit 0 ;;
|
|
85
|
+
esac
|
|
86
|
+
|
|
87
|
+
BG="$(printf '%s\n' "$INPUT" | jq -r '.tool_input.run_in_background // false' 2>/dev/null)"
|
|
88
|
+
[ "$BG" = "true" ] || exit 0
|
|
89
|
+
|
|
90
|
+
# 親(top-level)からの背景の生成は通す。止めたいのは入れ子の側だけ。
|
|
91
|
+
[ -n "${CLAUDE_CODE_CHILD_SESSION:-}" ] || exit 0
|
|
92
|
+
|
|
93
|
+
cat >&2 <<'MSG'
|
|
94
|
+
Blocked: a sub-agent tried to spawn a background agent.
|
|
95
|
+
|
|
96
|
+
Issue #73829: nested background agents orphan and loop. Once the intermediate
|
|
97
|
+
agent's session ends, TaskStop/TaskOutput return "No task found" while the tasks
|
|
98
|
+
keep running and burning tokens — 6.5 hours and several hundred USD in the
|
|
99
|
+
original report.
|
|
100
|
+
|
|
101
|
+
Since Claude Code 2.1.219 the default nesting depth is 3 (was 1), so this shape
|
|
102
|
+
now has three levels to compound through instead of one.
|
|
103
|
+
|
|
104
|
+
Do one of these instead:
|
|
105
|
+
- Do the sub-topics inline in this sub-agent (no further dispatch).
|
|
106
|
+
- Spawn background agents only from the top-level session, where TaskStop works.
|
|
107
|
+
- If you genuinely need nesting, cap it first: CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH=1
|
|
108
|
+
MSG
|
|
109
|
+
exit 2
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# nested-spawn-inflight-guard.sh — Refuse Task/SendMessage dispatch when too many subagents are already in flight
|
|
3
|
+
#
|
|
4
|
+
# Why: Issue #62193 (fdpr-H, 2026-05-25 — 3,079 bash subprocesses spawned in 17s,
|
|
5
|
+
# hard reboot required) and the 2026-05-29 follow-up from @allenfu000 (Windows,
|
|
6
|
+
# v2.1.156, Opus 4.8 ultracode workflow — subagents spawning nested PowerShell
|
|
7
|
+
# until OOM, taking down two other Claude Code windows alongside) are the two
|
|
8
|
+
# canonical reproductions of Cluster 1's nested-spawn sub-pattern: uncapped
|
|
9
|
+
# fan-out at the orchestration layer rather than inside a single tool call.
|
|
10
|
+
#
|
|
11
|
+
# Two existing cc-safe-setup hooks address the same architectural surface
|
|
12
|
+
# with different approaches:
|
|
13
|
+
#
|
|
14
|
+
# - max-concurrent-agents.sh uses a /tmp counter file that increments on
|
|
15
|
+
# dispatch but never decrements — relies on file-age expiry (10 min) to
|
|
16
|
+
# reset. Over-counts on the rebound path (counter persists after agents
|
|
17
|
+
# complete), under-counts on burst recovery (file mtime resets the
|
|
18
|
+
# window for unrelated samples).
|
|
19
|
+
#
|
|
20
|
+
# - subagent-budget-guard.sh uses a per-line timestamp tracker in
|
|
21
|
+
# ~/.claude/active-agents with a 30-minute "active" window. Same
|
|
22
|
+
# time-window approximation; same dual error mode.
|
|
23
|
+
#
|
|
24
|
+
# Both also match only the legacy tool_name "Agent", missing the modern
|
|
25
|
+
# "Task" and "SendMessage" dispatcher entry points.
|
|
26
|
+
#
|
|
27
|
+
# This hook reads the actual transcript at dispatch time, counts in-flight
|
|
28
|
+
# subagents (tool_use entries with no matching tool_result), and refuses
|
|
29
|
+
# the new dispatch when the count exceeds the configured budget. Because
|
|
30
|
+
# the count comes from the transcript itself, there is no stale-state
|
|
31
|
+
# window and no counter to leak.
|
|
32
|
+
#
|
|
33
|
+
# Event: PreToolUse MATCHER: "Task|Agent|SendMessage"
|
|
34
|
+
# Action: Scan the transcript for tool_use entries whose name matches the
|
|
35
|
+
# dispatcher family (Task / Agent / SendMessage). Subtract those that
|
|
36
|
+
# already have a tool_result with the same tool_use_id. If the
|
|
37
|
+
# remaining count (in-flight) >= CC_NESTED_SPAWN_BUDGET, exit 2 with
|
|
38
|
+
# a stderr advisory naming the budget, the counted in-flight ids,
|
|
39
|
+
# and the override path. Otherwise exit 0.
|
|
40
|
+
#
|
|
41
|
+
# Configuration (all optional):
|
|
42
|
+
# CC_NESTED_SPAWN_BUDGET Max concurrent in-flight subagents (default: 5)
|
|
43
|
+
# CC_NESTED_SPAWN_DISABLE Set to "1" to bypass entirely (escape hatch)
|
|
44
|
+
# CC_NESTED_SPAWN_LOOKBACK Number of trailing transcript lines to scan
|
|
45
|
+
# (default: 2000; raise for very long sessions)
|
|
46
|
+
#
|
|
47
|
+
# Override one specific dispatch (clear after the call to re-arm):
|
|
48
|
+
# CC_NESTED_SPAWN_OVERRIDE=1 claude ...
|
|
49
|
+
#
|
|
50
|
+
# Reading the in-flight set (manual inspection):
|
|
51
|
+
# jq -c 'select(.message.content[]?.type=="tool_use" and
|
|
52
|
+
# (.message.content[].name|test("Task|Agent|SendMessage")))' \
|
|
53
|
+
# ~/.claude/projects/*/SESSION.jsonl
|
|
54
|
+
|
|
55
|
+
set -u
|
|
56
|
+
|
|
57
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
58
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
59
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
60
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
61
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
62
|
+
_nojq_warned="/tmp/cc-nojq-warned-nested-spawn-inflight-guard-$PPID"
|
|
63
|
+
[ -f "$_nojq_warned" ] || {
|
|
64
|
+
echo "WARNING [nested-spawn-inflight-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
65
|
+
: > "$_nojq_warned"
|
|
66
|
+
}
|
|
67
|
+
fi
|
|
68
|
+
|
|
69
|
+
BUDGET="${CC_NESTED_SPAWN_BUDGET:-5}"
|
|
70
|
+
LOOKBACK="${CC_NESTED_SPAWN_LOOKBACK:-2000}"
|
|
71
|
+
DISABLE="${CC_NESTED_SPAWN_DISABLE:-0}"
|
|
72
|
+
OVERRIDE="${CC_NESTED_SPAWN_OVERRIDE:-0}"
|
|
73
|
+
|
|
74
|
+
# Escape hatches: disable entirely, or override one specific call.
|
|
75
|
+
if [ "$DISABLE" = "1" ] || [ "$OVERRIDE" = "1" ]; then
|
|
76
|
+
exit 0
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
INPUT=$(cat)
|
|
80
|
+
|
|
81
|
+
# Only act when the tool being dispatched is itself a subagent dispatcher.
|
|
82
|
+
TOOL=$(printf '%s' "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
|
|
83
|
+
case "$TOOL" in
|
|
84
|
+
Task|Agent|SendMessage) ;;
|
|
85
|
+
*) exit 0 ;;
|
|
86
|
+
esac
|
|
87
|
+
|
|
88
|
+
# Locate the transcript. Without it we can't measure in-flight state — fail open.
|
|
89
|
+
TRANSCRIPT=$(printf '%s' "$INPUT" | jq -r '.transcript_path // empty' 2>/dev/null)
|
|
90
|
+
if [ -z "$TRANSCRIPT" ] || [ ! -r "$TRANSCRIPT" ]; then
|
|
91
|
+
exit 0
|
|
92
|
+
fi
|
|
93
|
+
|
|
94
|
+
# Sanity-check the budget; nonsense values fail open.
|
|
95
|
+
case "$BUDGET" in
|
|
96
|
+
''|*[!0-9]*) exit 0 ;;
|
|
97
|
+
esac
|
|
98
|
+
case "$LOOKBACK" in
|
|
99
|
+
''|*[!0-9]*) LOOKBACK=2000 ;;
|
|
100
|
+
esac
|
|
101
|
+
|
|
102
|
+
# Collect dispatched ids (tool_use entries with name in the dispatcher family)
|
|
103
|
+
# and resolved ids (tool_result entries) from the trailing window of the
|
|
104
|
+
# transcript. The set difference is the in-flight set.
|
|
105
|
+
#
|
|
106
|
+
# Two transcript shapes are common:
|
|
107
|
+
# - {"message": {"content": [...]}} (assistant turns + user turns)
|
|
108
|
+
# - {"type":"tool_use","id":"...","name":"..."} (some hook payload echoes)
|
|
109
|
+
#
|
|
110
|
+
# We accept both. jq extracts the union by trying each path.
|
|
111
|
+
ANALYSIS=$(tail -n "$LOOKBACK" "$TRANSCRIPT" 2>/dev/null | \
|
|
112
|
+
jq -rs '
|
|
113
|
+
def extract_tool_use:
|
|
114
|
+
(.message.content // [.])[] |
|
|
115
|
+
select(type == "object" and .type == "tool_use") |
|
|
116
|
+
select(.name | test("^(Task|Agent|SendMessage)$"; "")) |
|
|
117
|
+
.id // empty;
|
|
118
|
+
def extract_tool_result:
|
|
119
|
+
(.message.content // [.])[] |
|
|
120
|
+
select(type == "object" and .type == "tool_result") |
|
|
121
|
+
.tool_use_id // empty;
|
|
122
|
+
|
|
123
|
+
. as $rows |
|
|
124
|
+
($rows | map(extract_tool_use) | flatten | map(select(. != ""))) as $dispatched |
|
|
125
|
+
($rows | map(extract_tool_result) | flatten | map(select(. != ""))) as $resolved |
|
|
126
|
+
($dispatched - $resolved) as $inflight |
|
|
127
|
+
{
|
|
128
|
+
inflight_count: ($inflight | length),
|
|
129
|
+
inflight_ids: $inflight
|
|
130
|
+
} |
|
|
131
|
+
@json
|
|
132
|
+
' 2>/dev/null)
|
|
133
|
+
|
|
134
|
+
# If the jq pipeline failed, fail open — never block on hook bugs.
|
|
135
|
+
if [ -z "$ANALYSIS" ]; then
|
|
136
|
+
exit 0
|
|
137
|
+
fi
|
|
138
|
+
|
|
139
|
+
INFLIGHT_COUNT=$(printf '%s' "$ANALYSIS" | jq -r '.inflight_count // 0' 2>/dev/null)
|
|
140
|
+
case "$INFLIGHT_COUNT" in
|
|
141
|
+
''|*[!0-9]*) exit 0 ;;
|
|
142
|
+
esac
|
|
143
|
+
|
|
144
|
+
# If at or above the budget, the new dispatch would push us into runaway territory.
|
|
145
|
+
# Refuse with a stderr advisory.
|
|
146
|
+
if [ "$INFLIGHT_COUNT" -ge "$BUDGET" ]; then
|
|
147
|
+
IDS=$(printf '%s' "$ANALYSIS" | jq -r '.inflight_ids | join(", ")' 2>/dev/null)
|
|
148
|
+
cat >&2 <<EOF
|
|
149
|
+
BLOCKED: ${INFLIGHT_COUNT} subagent(s) already in flight (budget: ${BUDGET}).
|
|
150
|
+
In-flight ids: ${IDS}
|
|
151
|
+
This dispatch would push the count to $((INFLIGHT_COUNT + 1)). Wait for one
|
|
152
|
+
or more to complete (tool_result) before dispatching another, or raise the
|
|
153
|
+
budget via CC_NESTED_SPAWN_BUDGET=N for legitimate fan-out workloads.
|
|
154
|
+
|
|
155
|
+
To allow this specific call without changing the budget:
|
|
156
|
+
CC_NESTED_SPAWN_OVERRIDE=1 (clears after the next dispatch)
|
|
157
|
+
To disable the guard entirely:
|
|
158
|
+
CC_NESTED_SPAWN_DISABLE=1
|
|
159
|
+
|
|
160
|
+
Root cause, if you never wanted nesting: subagents spawning subagents is
|
|
161
|
+
opt-out at the source.
|
|
162
|
+
CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH=1
|
|
163
|
+
Set it explicitly rather than relying on the default. Verified in 2.1.220 by
|
|
164
|
+
reading the shipped binary: the depth default is fetched from a remote config
|
|
165
|
+
and only falls back to the built-in 3 when that fetch yields nothing, so the
|
|
166
|
+
changelog's "default is 3" is a fallback, not a guarantee. The two sibling
|
|
167
|
+
caps are plain constants by contrast (concurrent 20, per-session 200).
|
|
168
|
+
|
|
169
|
+
Why this guard exists: Issue #62193 (3,079 bash subprocesses in 17s, hard
|
|
170
|
+
reboot) and the 2026-05-29 Windows follow-up (ultracode subagents spawning
|
|
171
|
+
PowerShell until two other Claude Code windows crashed). Cluster 1
|
|
172
|
+
(Sub-Agent Observability) nested-spawn sub-pattern.
|
|
173
|
+
See: https://github.com/yurukusa/cc-safe-setup/blob/main/docs/cluster-tracker.html#cluster-soh
|
|
174
|
+
EOF
|
|
175
|
+
exit 2
|
|
176
|
+
fi
|
|
177
|
+
|
|
178
|
+
exit 0
|
|
@@ -13,6 +13,18 @@
|
|
|
13
13
|
|
|
14
14
|
set -euo pipefail
|
|
15
15
|
|
|
16
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
17
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
18
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
19
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
20
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
21
|
+
_nojq_warned="/tmp/cc-nojq-warned-network-exfil-guard-$PPID"
|
|
22
|
+
[ -f "$_nojq_warned" ] || {
|
|
23
|
+
echo "WARNING [network-exfil-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
24
|
+
: > "$_nojq_warned"
|
|
25
|
+
}
|
|
26
|
+
fi
|
|
27
|
+
|
|
16
28
|
INPUT=$(cat)
|
|
17
29
|
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
18
30
|
[ -z "$COMMAND" ] && exit 0
|
|
@@ -18,6 +18,18 @@
|
|
|
18
18
|
#
|
|
19
19
|
# TRIGGER: PreToolUse MATCHER: "Bash"
|
|
20
20
|
|
|
21
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
22
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
23
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
24
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
25
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
26
|
+
_nojq_warned="/tmp/cc-nojq-warned-network-guard-$PPID"
|
|
27
|
+
[ -f "$_nojq_warned" ] || {
|
|
28
|
+
echo "WARNING [network-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
29
|
+
: > "$_nojq_warned"
|
|
30
|
+
}
|
|
31
|
+
fi
|
|
32
|
+
|
|
21
33
|
INPUT=$(cat)
|
|
22
34
|
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
23
35
|
|
|
@@ -13,6 +13,18 @@
|
|
|
13
13
|
#
|
|
14
14
|
# TRIGGER: PreToolUse MATCHER: "Bash"
|
|
15
15
|
|
|
16
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
17
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
18
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
19
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
20
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
21
|
+
_nojq_warned="/tmp/cc-nojq-warned-network-interface-guard-$PPID"
|
|
22
|
+
[ -f "$_nojq_warned" ] || {
|
|
23
|
+
echo "WARNING [network-interface-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
24
|
+
: > "$_nojq_warned"
|
|
25
|
+
}
|
|
26
|
+
fi
|
|
27
|
+
|
|
16
28
|
INPUT=$(cat)
|
|
17
29
|
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
18
30
|
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
# }
|
|
22
22
|
# ================================================================
|
|
23
23
|
#
|
|
24
|
-
# TRIGGER:
|
|
24
|
+
# TRIGGER: PostToolUse MATCHER: "Edit|Write"
|
|
25
25
|
|
|
26
26
|
INPUT=$(cat)
|
|
27
27
|
FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/examples/no-any-type.sh
CHANGED
|
File without changes
|
package/examples/no-ask-human.sh
CHANGED
|
@@ -23,6 +23,18 @@
|
|
|
23
23
|
# }
|
|
24
24
|
# ================================================================
|
|
25
25
|
|
|
26
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
27
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
28
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
29
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
30
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
31
|
+
_nojq_warned="/tmp/cc-nojq-warned-no-ask-human-$PPID"
|
|
32
|
+
[ -f "$_nojq_warned" ] || {
|
|
33
|
+
echo "WARNING [no-ask-human]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
34
|
+
: > "$_nojq_warned"
|
|
35
|
+
}
|
|
36
|
+
fi
|
|
37
|
+
|
|
26
38
|
INPUT=$(cat)
|
|
27
39
|
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
28
40
|
[ -z "$COMMAND" ] && exit 0
|
|
File without changes
|
|
@@ -7,6 +7,18 @@
|
|
|
7
7
|
# TRIGGER: PreToolUse
|
|
8
8
|
# MATCHER: "Bash"
|
|
9
9
|
|
|
10
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
11
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
12
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
13
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
14
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
15
|
+
_nojq_warned="/tmp/cc-nojq-warned-no-base64-exfil-$PPID"
|
|
16
|
+
[ -f "$_nojq_warned" ] || {
|
|
17
|
+
echo "WARNING [no-base64-exfil]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
18
|
+
: > "$_nojq_warned"
|
|
19
|
+
}
|
|
20
|
+
fi
|
|
21
|
+
|
|
10
22
|
INPUT=$(cat)
|
|
11
23
|
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
12
24
|
[ -z "$COMMAND" ] && exit 0
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|