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
|
@@ -15,6 +15,18 @@
|
|
|
15
15
|
|
|
16
16
|
set -euo pipefail
|
|
17
17
|
|
|
18
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
19
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
20
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
21
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
22
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
23
|
+
_nojq_warned="/tmp/cc-nojq-warned-background-task-guard-$PPID"
|
|
24
|
+
[ -f "$_nojq_warned" ] || {
|
|
25
|
+
echo "WARNING [background-task-guard]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
26
|
+
: > "$_nojq_warned"
|
|
27
|
+
}
|
|
28
|
+
fi
|
|
29
|
+
|
|
18
30
|
INPUT=$(cat)
|
|
19
31
|
CMD=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
20
32
|
[ -z "$CMD" ] && exit 0
|
|
File without changes
|
|
@@ -21,6 +21,18 @@
|
|
|
21
21
|
# CC_BANNED_COMMANDS — colon-separated list of regex patterns to block
|
|
22
22
|
# Default: "sed -i:awk -i inplace:perl -pi:perl .*-i"
|
|
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-banned-command-guard-$PPID"
|
|
30
|
+
[ -f "$_nojq_warned" ] || {
|
|
31
|
+
echo "WARNING [banned-command-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
|
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ================================================================
|
|
3
|
+
# bash-allowlist-secondary-check.sh — Re-check Bash commands against
|
|
4
|
+
# the user's settings.json allowlist
|
|
5
|
+
# ================================================================
|
|
6
|
+
# PURPOSE:
|
|
7
|
+
# When the Bash tool fires, this hook independently parses the
|
|
8
|
+
# allowlist from `.claude/settings.json` (and global
|
|
9
|
+
# `~/.claude/settings.json`) and verifies the command matches an
|
|
10
|
+
# allowed pattern. If no pattern matches, it warns to stderr (or
|
|
11
|
+
# blocks in strict mode) — providing a second line of defence
|
|
12
|
+
# against authorization-layer bypasses.
|
|
13
|
+
#
|
|
14
|
+
# TRIGGER: PreToolUse
|
|
15
|
+
# MATCHER: "Bash"
|
|
16
|
+
#
|
|
17
|
+
# WHY THIS MATTERS:
|
|
18
|
+
# Issue #56117 reported that during a session running a Skill,
|
|
19
|
+
# `Bash` tool calls for commands NOT present in the settings.json
|
|
20
|
+
# allowlist (e.g. `git add`, `git commit`, `git push`) executed
|
|
21
|
+
# without triggering the authorization prompt. The user was never
|
|
22
|
+
# asked to approve. The allowlist contained only `git diff`, `git
|
|
23
|
+
# log`, `git status`, no `Bash(*)` broad rule, and
|
|
24
|
+
# `--dangerously-skip-permissions` was not used.
|
|
25
|
+
#
|
|
26
|
+
# This is an authorization-layer bypass: the tool that should have
|
|
27
|
+
# enforced the allowlist failed to do so silently. Skills, custom
|
|
28
|
+
# agents, or other inner contexts may continue to expose similar
|
|
29
|
+
# bypasses.
|
|
30
|
+
#
|
|
31
|
+
# This hook re-evaluates the allowlist independently of Claude
|
|
32
|
+
# Code's internal logic. It does not replace the primary check —
|
|
33
|
+
# it backs it up.
|
|
34
|
+
#
|
|
35
|
+
# WHAT IT CHECKS:
|
|
36
|
+
# 1. Reads `permissions.allow` from `.claude/settings.json` (project)
|
|
37
|
+
# and `~/.claude/settings.json` (user). Local settings
|
|
38
|
+
# (`.claude/settings.local.json`) are also merged.
|
|
39
|
+
# 2. Extracts Bash patterns of the form `Bash(<pattern>)`.
|
|
40
|
+
# 3. Tests the Bash command against each pattern using a simple
|
|
41
|
+
# matcher: exact match, prefix match for patterns ending in `:*`,
|
|
42
|
+
# and wildcard for `Bash(*)`.
|
|
43
|
+
# 4. If no pattern matches, emits a warning that names the command
|
|
44
|
+
# and references #56117.
|
|
45
|
+
#
|
|
46
|
+
# OUTPUT:
|
|
47
|
+
# Warning to stderr when the command does not match any allowlist
|
|
48
|
+
# pattern. Default: exit 0 (advisory). Strict mode: exit 2 (block).
|
|
49
|
+
#
|
|
50
|
+
# CONFIGURATION:
|
|
51
|
+
# CC_BASH_ALLOWLIST_STRICT — set to "1" to block when no pattern
|
|
52
|
+
# matches (default: warn only)
|
|
53
|
+
# CC_BASH_ALLOWLIST_QUIET — set to "1" to silence warnings (still
|
|
54
|
+
# blocks in strict mode)
|
|
55
|
+
#
|
|
56
|
+
# LIMITATIONS:
|
|
57
|
+
# - The matcher is intentionally simple. It does not perfectly
|
|
58
|
+
# replicate Claude Code's internal matching, which uses richer
|
|
59
|
+
# glob semantics. Some allowlist entries may produce false
|
|
60
|
+
# warnings; tune patterns or use strict mode selectively.
|
|
61
|
+
# - The hook reads JSON via `jq`. If `jq` is missing, the hook
|
|
62
|
+
# exits 0 silently rather than failing the Bash call.
|
|
63
|
+
# - This hook does not record approvals. Repeated commands matching
|
|
64
|
+
# the same gap will repeat the warning.
|
|
65
|
+
#
|
|
66
|
+
# RELATED ISSUES:
|
|
67
|
+
# https://github.com/anthropics/claude-code/issues/56117
|
|
68
|
+
# ================================================================
|
|
69
|
+
|
|
70
|
+
set -u
|
|
71
|
+
|
|
72
|
+
INPUT=$(cat)
|
|
73
|
+
COMMAND=$(printf '%s' "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
74
|
+
|
|
75
|
+
# No command, nothing to check.
|
|
76
|
+
[ -z "$COMMAND" ] && exit 0
|
|
77
|
+
|
|
78
|
+
# jq is required to read settings; fall through silently if missing.
|
|
79
|
+
command -v jq >/dev/null 2>&1 || exit 0
|
|
80
|
+
|
|
81
|
+
STRICT="${CC_BASH_ALLOWLIST_STRICT:-0}"
|
|
82
|
+
QUIET="${CC_BASH_ALLOWLIST_QUIET:-0}"
|
|
83
|
+
|
|
84
|
+
# Collect allow patterns from up to three settings files.
|
|
85
|
+
collect_allow_patterns() {
|
|
86
|
+
local f
|
|
87
|
+
for f in \
|
|
88
|
+
"$HOME/.claude/settings.json" \
|
|
89
|
+
".claude/settings.json" \
|
|
90
|
+
".claude/settings.local.json"
|
|
91
|
+
do
|
|
92
|
+
[ -r "$f" ] || continue
|
|
93
|
+
jq -r '.permissions.allow // [] | .[]' "$f" 2>/dev/null
|
|
94
|
+
done
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
PATTERNS=$(collect_allow_patterns)
|
|
98
|
+
|
|
99
|
+
# Extract only Bash() patterns. Other tools are out of scope.
|
|
100
|
+
BASH_PATTERNS=$(printf '%s\n' "$PATTERNS" | grep -E '^Bash\(' | sed -E 's/^Bash\((.*)\)$/\1/')
|
|
101
|
+
|
|
102
|
+
# Strip outer whitespace from the command for matching purposes.
|
|
103
|
+
TRIMMED_CMD=$(printf '%s' "$COMMAND" | sed -E 's/^[[:space:]]+//;s/[[:space:]]+$//')
|
|
104
|
+
|
|
105
|
+
# A Bash(*) pattern allows everything — matches and exits.
|
|
106
|
+
if printf '%s\n' "$BASH_PATTERNS" | grep -qx '\*'; then
|
|
107
|
+
exit 0
|
|
108
|
+
fi
|
|
109
|
+
|
|
110
|
+
# Try to match the command against any pattern.
|
|
111
|
+
matched=0
|
|
112
|
+
while IFS= read -r pat; do
|
|
113
|
+
[ -z "$pat" ] && continue
|
|
114
|
+
case "$pat" in
|
|
115
|
+
*":*")
|
|
116
|
+
# Prefix match: pattern is "<prefix>:*" — match if the command starts with <prefix>.
|
|
117
|
+
prefix="${pat%:\*}"
|
|
118
|
+
case "$TRIMMED_CMD" in
|
|
119
|
+
"$prefix"|"$prefix "*|"$prefix"$'\t'*)
|
|
120
|
+
matched=1
|
|
121
|
+
break
|
|
122
|
+
;;
|
|
123
|
+
esac
|
|
124
|
+
;;
|
|
125
|
+
*)
|
|
126
|
+
# Exact-or-prefix-with-space: pattern matches if the command is exactly the
|
|
127
|
+
# pattern, or the pattern is the leading token followed by a space/tab.
|
|
128
|
+
case "$TRIMMED_CMD" in
|
|
129
|
+
"$pat"|"$pat "*|"$pat"$'\t'*)
|
|
130
|
+
matched=1
|
|
131
|
+
break
|
|
132
|
+
;;
|
|
133
|
+
esac
|
|
134
|
+
;;
|
|
135
|
+
esac
|
|
136
|
+
done <<< "$BASH_PATTERNS"
|
|
137
|
+
|
|
138
|
+
if [ "$matched" -eq 1 ]; then
|
|
139
|
+
exit 0
|
|
140
|
+
fi
|
|
141
|
+
|
|
142
|
+
# No match. Emit a warning unless quiet, and block in strict mode.
|
|
143
|
+
if [ "$QUIET" != "1" ]; then
|
|
144
|
+
SHORT_CMD=$(printf '%s' "$TRIMMED_CMD" | head -c 120)
|
|
145
|
+
printf '⚠️ Bash command not matched by any settings.json allow pattern (Issue #56117 defence-in-depth):\n' >&2
|
|
146
|
+
printf ' command: %s\n' "$SHORT_CMD" >&2
|
|
147
|
+
printf ' note: Claude Code should have prompted before running this. If it did not, the\n' >&2
|
|
148
|
+
printf ' primary allowlist check may have been bypassed (e.g. inside a Skill).\n' >&2
|
|
149
|
+
printf ' action: Add an explicit allow rule, deny the run, or set CC_BASH_ALLOWLIST_STRICT=1 to block.\n' >&2
|
|
150
|
+
printf ' issue: https://github.com/anthropics/claude-code/issues/56117\n' >&2
|
|
151
|
+
fi
|
|
152
|
+
|
|
153
|
+
if [ "$STRICT" = "1" ]; then
|
|
154
|
+
exit 2
|
|
155
|
+
fi
|
|
156
|
+
|
|
157
|
+
exit 0
|
|
@@ -24,6 +24,18 @@
|
|
|
24
24
|
# Configuration: Set CC_ALLOWED_DOMAINS env var (comma-separated)
|
|
25
25
|
# or edit the ALLOWED_DOMAINS array below.
|
|
26
26
|
|
|
27
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
28
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
29
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
30
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
31
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
32
|
+
_nojq_warned="/tmp/cc-nojq-warned-bash-domain-allowlist-$PPID"
|
|
33
|
+
[ -f "$_nojq_warned" ] || {
|
|
34
|
+
echo "WARNING [bash-domain-allowlist]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
35
|
+
: > "$_nojq_warned"
|
|
36
|
+
}
|
|
37
|
+
fi
|
|
38
|
+
|
|
27
39
|
INPUT=$(cat)
|
|
28
40
|
CMD=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
29
41
|
[ -z "$CMD" ] && exit 0
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ================================================================
|
|
3
|
+
# bash-fanout-bounded-rewriter.sh — Detect and refuse unbounded
|
|
4
|
+
# bash fan-out patterns that can spawn thousands of subprocesses
|
|
5
|
+
# ================================================================
|
|
6
|
+
# PURPOSE:
|
|
7
|
+
# Issue #62193 documented a 3,079-bash-in-17-seconds spawn event
|
|
8
|
+
# from a single Bash tool call, leading to an OS-level lockup
|
|
9
|
+
# (1.4 TB VSZ on parent, contiguous PIDs 21300-24379, OOM killer
|
|
10
|
+
# hitting `code` first). The pattern: a single Bash command that
|
|
11
|
+
# internally fans out (find ... -exec, unbounded loops, parallel
|
|
12
|
+
# without -j N, xargs without -P N) hands the kernel an
|
|
13
|
+
# uncapped concurrency demand.
|
|
14
|
+
#
|
|
15
|
+
# The cleanest architectural answer is cgroup-based isolation
|
|
16
|
+
# (systemd-run --scope -p TasksMax=N). That works but renders
|
|
17
|
+
# bash useless under pressure because every command including
|
|
18
|
+
# light single-process ones hits the TasksMax ceiling.
|
|
19
|
+
#
|
|
20
|
+
# This hook covers the gap: detect fan-out signatures in the
|
|
21
|
+
# bash command BEFORE the shell sees them. Refuse the call with
|
|
22
|
+
# a clear advisory naming the unbounded pattern and a bounded
|
|
23
|
+
# rewrite (xargs -P N -n 1, parallel -j N, GNU make -j N).
|
|
24
|
+
#
|
|
25
|
+
# WHO THIS PROTECTS:
|
|
26
|
+
# Operators running Claude Code on a workstation where a single
|
|
27
|
+
# uncapped fan-out can lock the OS. Especially relevant when
|
|
28
|
+
# running on Max-plan accounts where the model is more willing
|
|
29
|
+
# to generate aggressive parallelism.
|
|
30
|
+
#
|
|
31
|
+
# DETECTION:
|
|
32
|
+
# PreToolUse on Bash. Scan the command string for fan-out
|
|
33
|
+
# signatures in order of severity:
|
|
34
|
+
# 1. find ... -exec (worst: shell-spawning per result)
|
|
35
|
+
# 2. for ... in ... ; do (unbounded loop)
|
|
36
|
+
# 3. while read ... ; do (unbounded loop)
|
|
37
|
+
# 4. xargs without -P N -n N (single process per line)
|
|
38
|
+
# 5. parallel without -j N (defaults to one-per-core)
|
|
39
|
+
# 6. GNU make -j (without explicit N; defaults to infinite)
|
|
40
|
+
# 7. seq N | while ... (high-N sequence to loop)
|
|
41
|
+
#
|
|
42
|
+
# OUTPUT:
|
|
43
|
+
# On detection, blocks the call (exit 2) with a stderr message
|
|
44
|
+
# that names the matched pattern and shows a bounded rewrite.
|
|
45
|
+
# The operator can override per-call by setting
|
|
46
|
+
# CC_BASH_FANOUT_OVERRIDE=1 (e.g., for legitimate parallelism)
|
|
47
|
+
# or globally with CC_BASH_FANOUT_DISABLE=1.
|
|
48
|
+
#
|
|
49
|
+
# CONFIGURATION:
|
|
50
|
+
# CC_BASH_FANOUT_DISABLE — set to 1 to disable entirely
|
|
51
|
+
# CC_BASH_FANOUT_OVERRIDE — set to 1 to allow this call once
|
|
52
|
+
# (clear after the call to re-arm)
|
|
53
|
+
# CC_BASH_FANOUT_MAX_LOOP_LINES — refuse loops with more than
|
|
54
|
+
# this many lines in the body
|
|
55
|
+
# (default: refuse all unbounded)
|
|
56
|
+
# CC_BASH_FANOUT_PARALLEL_BOUND — default bounded N to suggest
|
|
57
|
+
# in advisories (default: 8)
|
|
58
|
+
#
|
|
59
|
+
# RELATED ISSUES:
|
|
60
|
+
# https://github.com/anthropics/claude-code/issues/62193
|
|
61
|
+
#
|
|
62
|
+
# TRIGGER: PreToolUse
|
|
63
|
+
# MATCHER: "Bash"
|
|
64
|
+
# ================================================================
|
|
65
|
+
|
|
66
|
+
set -u
|
|
67
|
+
|
|
68
|
+
# Without jq, the parse below silently yields empty and this hook stops
|
|
69
|
+
# guarding - with no error anywhere. Say so. We deliberately do not exit
|
|
70
|
+
# here: blocking would halt every tool call, and exiting 0 would change
|
|
71
|
+
# the behaviour of guards that do not depend on the parsed value.
|
|
72
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
73
|
+
_nojq_warned="/tmp/cc-nojq-warned-bash-fanout-bounded-rewriter-$PPID"
|
|
74
|
+
[ -f "$_nojq_warned" ] || {
|
|
75
|
+
echo "WARNING [bash-fanout-bounded-rewriter]: jq not found - this hook cannot inspect tool calls and is NOT protecting you. Install jq." >&2
|
|
76
|
+
: > "$_nojq_warned"
|
|
77
|
+
}
|
|
78
|
+
fi
|
|
79
|
+
|
|
80
|
+
INPUT=$(cat 2>/dev/null || echo "{}")
|
|
81
|
+
|
|
82
|
+
[ "${CC_BASH_FANOUT_DISABLE:-0}" = "1" ] && exit 0
|
|
83
|
+
[ "${CC_BASH_FANOUT_OVERRIDE:-0}" = "1" ] && exit 0
|
|
84
|
+
|
|
85
|
+
COMMAND=$(printf '%s' "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
86
|
+
[ -z "$COMMAND" ] && exit 0
|
|
87
|
+
|
|
88
|
+
BOUND="${CC_BASH_FANOUT_PARALLEL_BOUND:-8}"
|
|
89
|
+
|
|
90
|
+
# Detection signatures, ordered most-severe-first
|
|
91
|
+
MATCHED_PATTERN=""
|
|
92
|
+
SUGGESTED_REWRITE=""
|
|
93
|
+
|
|
94
|
+
# Pattern 1: find ... -exec
|
|
95
|
+
if printf '%s' "$COMMAND" | grep -qE 'find +.*-exec +'; then
|
|
96
|
+
MATCHED_PATTERN="find ... -exec (shell-spawning per result, unbounded)"
|
|
97
|
+
SUGGESTED_REWRITE="find ... -print0 | xargs -0 -P $BOUND -n 1 <cmd>"
|
|
98
|
+
fi
|
|
99
|
+
|
|
100
|
+
# Pattern 2: for ... in ... ; do (only if the in-list is dynamic or large)
|
|
101
|
+
# Static lists like 'for i in 1 2 3' are fine; the danger is
|
|
102
|
+
# 'for f in $(...)', 'for f in *', or 'for f in $LIST'.
|
|
103
|
+
if [ -z "$MATCHED_PATTERN" ]; then
|
|
104
|
+
if printf '%s' "$COMMAND" | grep -qE 'for +[A-Za-z_][A-Za-z0-9_]* +in +(\$\(|`|\*|\$[A-Za-z_])'; then
|
|
105
|
+
MATCHED_PATTERN="for ... in \$(...) / glob / \$VAR (unbounded loop body)"
|
|
106
|
+
SUGGESTED_REWRITE="<list-source> | xargs -P $BOUND -n 1 <cmd>"
|
|
107
|
+
fi
|
|
108
|
+
fi
|
|
109
|
+
|
|
110
|
+
# Pattern 3: while read ... ; do
|
|
111
|
+
if [ -z "$MATCHED_PATTERN" ]; then
|
|
112
|
+
if printf '%s' "$COMMAND" | grep -qE 'while +(read|IFS=)'; then
|
|
113
|
+
MATCHED_PATTERN="while read ... (unbounded loop, one-process-per-line)"
|
|
114
|
+
SUGGESTED_REWRITE="<input> | xargs -P $BOUND -n 1 <cmd>"
|
|
115
|
+
fi
|
|
116
|
+
fi
|
|
117
|
+
|
|
118
|
+
# Pattern 4: xargs without -P
|
|
119
|
+
if [ -z "$MATCHED_PATTERN" ]; then
|
|
120
|
+
if printf '%s' "$COMMAND" | grep -qE 'xargs +' && \
|
|
121
|
+
! printf '%s' "$COMMAND" | grep -qE 'xargs +.*-P +[0-9]+'; then
|
|
122
|
+
MATCHED_PATTERN="xargs without -P N (defaults to single-process serial, OK; but if the upstream pipe is high-cardinality, refuse)"
|
|
123
|
+
# xargs without -P is actually safe (serial). Skip unless follows hi-card pipe.
|
|
124
|
+
# We don't actually block this — note for advisory only.
|
|
125
|
+
MATCHED_PATTERN="" # Reset; serial xargs is fine.
|
|
126
|
+
fi
|
|
127
|
+
fi
|
|
128
|
+
|
|
129
|
+
# Pattern 5: parallel without -j
|
|
130
|
+
if [ -z "$MATCHED_PATTERN" ]; then
|
|
131
|
+
if printf '%s' "$COMMAND" | grep -qE '(^| )parallel +' && \
|
|
132
|
+
! printf '%s' "$COMMAND" | grep -qE 'parallel +.*-j +[0-9]+'; then
|
|
133
|
+
MATCHED_PATTERN="GNU parallel without -j N (defaults to one-per-core, can exceed cgroup TasksMax)"
|
|
134
|
+
SUGGESTED_REWRITE="parallel -j $BOUND <cmd>"
|
|
135
|
+
fi
|
|
136
|
+
fi
|
|
137
|
+
|
|
138
|
+
# Pattern 6: make -j without N
|
|
139
|
+
if [ -z "$MATCHED_PATTERN" ]; then
|
|
140
|
+
if printf '%s' "$COMMAND" | grep -qE 'make +.*-j( |$)' && \
|
|
141
|
+
! printf '%s' "$COMMAND" | grep -qE 'make +.*-j *[0-9]+'; then
|
|
142
|
+
MATCHED_PATTERN="make -j without N (defaults to infinite parallelism)"
|
|
143
|
+
SUGGESTED_REWRITE="make -j$BOUND <target>"
|
|
144
|
+
fi
|
|
145
|
+
fi
|
|
146
|
+
|
|
147
|
+
# Pattern 7: seq N | (where N > 100)
|
|
148
|
+
if [ -z "$MATCHED_PATTERN" ]; then
|
|
149
|
+
SEQ_N=$(printf '%s' "$COMMAND" | grep -oE 'seq +[0-9]+' | head -1 | grep -oE '[0-9]+' || true)
|
|
150
|
+
if [ -n "$SEQ_N" ] && [ "$SEQ_N" -gt 100 ]; then
|
|
151
|
+
if printf '%s' "$COMMAND" | grep -qE 'seq +[0-9]+ *\| *(while|for|xargs)'; then
|
|
152
|
+
MATCHED_PATTERN="seq $SEQ_N piped to loop/xargs (high-cardinality fan-out)"
|
|
153
|
+
SUGGESTED_REWRITE="seq $SEQ_N | xargs -P $BOUND -n 1 <cmd>"
|
|
154
|
+
fi
|
|
155
|
+
fi
|
|
156
|
+
fi
|
|
157
|
+
|
|
158
|
+
# Nothing matched — pass through silently.
|
|
159
|
+
[ -z "$MATCHED_PATTERN" ] && exit 0
|
|
160
|
+
|
|
161
|
+
# Build the refusal message.
|
|
162
|
+
MSG="Unbounded fan-out detected: $MATCHED_PATTERN
|
|
163
|
+
|
|
164
|
+
This pattern can spawn an uncapped number of subprocesses. Issue #62193
|
|
165
|
+
documented a single Bash tool call that spawned 3,079 bash processes in
|
|
166
|
+
17 seconds, leading to an OS-level lockup (1.4 TB VSZ on parent, OOM
|
|
167
|
+
killer hitting Claude Code's parent process before reaching the runaways).
|
|
168
|
+
|
|
169
|
+
Bounded rewrite: $SUGGESTED_REWRITE
|
|
170
|
+
|
|
171
|
+
Why this layer (PreToolUse hook) instead of just cgroup TasksMax: a
|
|
172
|
+
TasksMax ceiling blocks ALL bash including light single-process calls,
|
|
173
|
+
rendering the tool useless under pressure. This hook intercepts only the
|
|
174
|
+
fan-out shape, so unrelated bash calls keep working at full speed.
|
|
175
|
+
|
|
176
|
+
Override for this one call:
|
|
177
|
+
CC_BASH_FANOUT_OVERRIDE=1 (then retry)
|
|
178
|
+
|
|
179
|
+
Disable entirely (operator already aware):
|
|
180
|
+
CC_BASH_FANOUT_DISABLE=1
|
|
181
|
+
|
|
182
|
+
The bounded rewrite is the actual safe form of the same command — it
|
|
183
|
+
runs the same workload at a cap of $BOUND concurrent processes, which is
|
|
184
|
+
sustainable on every workstation tested in the cc-safe-setup matrix.
|
|
185
|
+
|
|
186
|
+
Related: cc-safe-setup Cluster 1 (Sub-Agent Observability), scope
|
|
187
|
+
expansion sub-pattern. The OS-level manifestation of the same primitive."
|
|
188
|
+
|
|
189
|
+
echo "[bash-fanout-bounded-rewriter] $MSG" >&2
|
|
190
|
+
|
|
191
|
+
exit 2
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
# These cannot be bypassed with permissions.allow or acceptEdits.
|
|
12
12
|
#
|
|
13
13
|
# This PermissionRequest hook detects heuristic-triggered prompts and
|
|
14
|
-
# auto-approves them when
|
|
14
|
+
# auto-approves them when every command position is in a safe list.
|
|
15
15
|
#
|
|
16
16
|
# TRIGGER: PermissionRequest
|
|
17
17
|
# MATCHER: ""
|
|
@@ -25,6 +25,32 @@
|
|
|
25
25
|
# }]
|
|
26
26
|
# }
|
|
27
27
|
# }
|
|
28
|
+
#
|
|
29
|
+
# Fixed 2026-08-03. The safe list held bare command *words* — `git`, `curl`,
|
|
30
|
+
# `chmod`, `sed`, `node`, `python3`, `npx` — and a word says nothing about what
|
|
31
|
+
# the command does. `git commit -m "fix"` and `git push --force origin main`
|
|
32
|
+
# have the same first word.
|
|
33
|
+
#
|
|
34
|
+
# Measured against the shipped copy, over 20 destructive or credential-reading
|
|
35
|
+
# commands with no separator in them at all: **15 were approved**, among them
|
|
36
|
+
# `git push --force`, `git reset --hard`, `git clean -fdx`, `chmod -R 777 /`,
|
|
37
|
+
# `curl … | sh`, `node -e '…rmSync…'` and `cat ~/.aws/credentials`.
|
|
38
|
+
#
|
|
39
|
+
# ★ Measuring this hook needs the prompt text. It only acts when `.message`
|
|
40
|
+
# matches a heuristic warning, so a probe that puts the command in `.message`
|
|
41
|
+
# gets 0/20 back and reads as "no defect". The first sweep of this file did
|
|
42
|
+
# exactly that. A control — does a plainly safe command get approved at all? —
|
|
43
|
+
# is what separates "clean" from "not running".
|
|
44
|
+
#
|
|
45
|
+
# This is a different defect from the first-command-position one repaired in
|
|
46
|
+
# #937/#940/#941/#942/#943/#947, and mixing the two produces a number that looks
|
|
47
|
+
# right and is not: nothing here was hiding past a separator. (That defect was
|
|
48
|
+
# here too, and is fixed in the same pass.)
|
|
49
|
+
#
|
|
50
|
+
# Substitution is the subject of this hook, so it cannot simply refuse `$(…)`
|
|
51
|
+
# the way the others do. Instead the substitution's contents become command
|
|
52
|
+
# positions of their own and have to qualify: `echo $(git status)` is approved,
|
|
53
|
+
# `echo $(sudo rm -rf app)` is not.
|
|
28
54
|
|
|
29
55
|
INPUT=$(cat)
|
|
30
56
|
|
|
@@ -44,16 +70,92 @@ fi
|
|
|
44
70
|
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
45
71
|
[ -z "$COMMAND" ] && exit 0
|
|
46
72
|
|
|
47
|
-
#
|
|
48
|
-
|
|
73
|
+
# A redirection writes a file, whatever the command word says.
|
|
74
|
+
case "$COMMAND" in
|
|
75
|
+
*'>'*) exit 0 ;;
|
|
76
|
+
esac
|
|
49
77
|
|
|
50
|
-
#
|
|
51
|
-
|
|
78
|
+
# Command words that carry no destructive form of their own. Anything that takes
|
|
79
|
+
# code as an argument (`node -e`, `python3 -c`, `npx`) or fetches and runs
|
|
80
|
+
# (`curl`, `wget`) is deliberately absent: for those the word says nothing.
|
|
81
|
+
cc_base_ok() {
|
|
82
|
+
case "$1" in
|
|
83
|
+
cat|head|tail|less|more|wc|file|stat|du|df|ls|tree|\
|
|
84
|
+
which|whereis|type|realpath|readlink|basename|dirname|\
|
|
85
|
+
grep|rg|ag|ack|sort|uniq|tr|cut|column|nl|rev|awk|\
|
|
86
|
+
echo|printf|true|false|pwd|date|uname|hostname|whoami|id|\
|
|
87
|
+
jq|yq|cd|\
|
|
88
|
+
tsc|eslint|prettier|jest|vitest|pytest)
|
|
89
|
+
return 0 ;;
|
|
90
|
+
esac
|
|
91
|
+
return 1
|
|
92
|
+
}
|
|
52
93
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
94
|
+
# One line on purpose: inside single quotes a trailing backslash is a literal
|
|
95
|
+
# backslash-newline, not a continuation, and the pattern silently stops matching.
|
|
96
|
+
CC_SUBCMD_RE='^[[:space:]]*(git[[:space:]]+(status|log|diff|show|add|commit|branch|remote|describe|rev-parse|blame|shortlog|ls-files|ls-tree|fetch|stash[[:space:]]+(list|push|save))|npm[[:space:]]+(test|run|ci|ls|view|outdated)|yarn[[:space:]]+(test|run|info|why)|pnpm[[:space:]]+(test|run|list|why)|bun[[:space:]]+(test|run)|cargo[[:space:]]+(build|test|check|fmt|clippy|tree)|go[[:space:]]+(build|test|vet|fmt|list)|docker[[:space:]]+(ps|images|logs|inspect|version|info)|make[[:space:]]+[A-Za-z0-9_.-]+|pip[[:space:]]+(list|show|freeze)|python3[[:space:]]+-m[[:space:]]+(pytest|unittest|pip[[:space:]]+(list|show|freeze)))([[:space:]]|$)'
|
|
97
|
+
|
|
98
|
+
cc_subcommand_ok() {
|
|
99
|
+
printf '%s' "$1" | grep -qE "$CC_SUBCMD_RE"
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
cc_segment_base() {
|
|
103
|
+
printf '%s' "$1" \
|
|
104
|
+
| sed -E 's/^[[:space:]]+//; s/^([A-Za-z_][A-Za-z0-9_]*=[^[:space:]]*[[:space:]]+)*//' \
|
|
105
|
+
| awk '{print $1}' \
|
|
106
|
+
| sed 's|.*/||'
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
# `git branch` reads; `git branch -D main` deletes one. Same first two words.
|
|
110
|
+
CC_GIT_DESTRUCTIVE_RE='^[[:space:]]*git[[:space:]]+(branch|tag)[[:space:]]+-([dDmM]|-delete|-move)([[:space:]]|$)'
|
|
111
|
+
|
|
112
|
+
cc_segment_ok() {
|
|
113
|
+
local seg="$1" base
|
|
114
|
+
base=$(cc_segment_base "$seg")
|
|
115
|
+
[ -z "$base" ] && return 1
|
|
116
|
+
|
|
117
|
+
if [ "$base" = "find" ]; then
|
|
118
|
+
printf '%s' "$seg" \
|
|
119
|
+
| grep -qE '(^|[[:space:]])-(delete|exec|execdir|ok|okdir|fprintf?|fls|fprint0)([[:space:]]|$)' \
|
|
120
|
+
&& return 1
|
|
121
|
+
return 0
|
|
122
|
+
fi
|
|
123
|
+
if [ "$base" = "sed" ]; then
|
|
124
|
+
printf '%s' "$seg" | grep -qE '(^|[[:space:]])-[a-zA-Z]*i' && return 1
|
|
125
|
+
return 0
|
|
126
|
+
fi
|
|
127
|
+
|
|
128
|
+
cc_base_ok "$base" && return 0
|
|
129
|
+
printf '%s' "$seg" | grep -qE "$CC_GIT_DESTRUCTIVE_RE" && return 1
|
|
130
|
+
cc_subcommand_ok "$seg" && return 0
|
|
131
|
+
return 1
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
# Split into command positions. Substitutions become positions of their own,
|
|
135
|
+
# so what runs inside them has to qualify too. `)` is only turned into a break
|
|
136
|
+
# when a substitution was opened, so `awk '{print $1}'` is left intact.
|
|
137
|
+
SPLIT=$(printf '%s' "$COMMAND" | tr ';&|' '\n\n\n')
|
|
138
|
+
case "$COMMAND" in
|
|
139
|
+
*'$('*|*'`'*)
|
|
140
|
+
SPLIT=$(printf '%s' "$SPLIT" | sed 's/\$(/\n/g; s/`/\n/g; s/)/\n/g')
|
|
141
|
+
;;
|
|
142
|
+
esac
|
|
143
|
+
|
|
144
|
+
IDX=0
|
|
145
|
+
while IFS= read -r SEG; do
|
|
146
|
+
SEG="${SEG#"${SEG%%[![:space:]]*}"}"
|
|
147
|
+
SEG="${SEG%"${SEG##*[![:space:]]}"}"
|
|
148
|
+
# a fragment left over from splitting — a lone quote, a stray brace — is not
|
|
149
|
+
# a command position
|
|
150
|
+
STRIPPED=$(printf '%s' "$SEG" | tr -d "\"'{} ")
|
|
151
|
+
[ -z "$STRIPPED" ] && continue
|
|
152
|
+
cc_segment_ok "$SEG" || exit 0
|
|
153
|
+
IDX=$((IDX + 1))
|
|
154
|
+
done <<EOF
|
|
155
|
+
$SPLIT
|
|
156
|
+
EOF
|
|
157
|
+
|
|
158
|
+
[ "$IDX" -eq 0 ] && exit 0
|
|
57
159
|
|
|
58
|
-
|
|
160
|
+
jq -n '{"hookSpecificOutput":{"hookEventName":"PermissionRequest","decision":{"behavior":"allow"}}}'
|
|
59
161
|
exit 0
|