cc-safe-setup 29.8.0 → 30.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +72 -19
- package/.claude-plugin/plugin.json +1 -1
- package/CONTRIBUTING.md +7 -2
- package/COOKBOOK.md +50 -46
- package/LICENSE +21 -0
- package/MIGRATION.md +8 -8
- package/README.md +421 -512
- package/SAFETY_CHECKLIST.md +15 -7
- package/SERVICES.md +194 -0
- package/SETTINGS_REFERENCE.md +236 -17
- package/SKILL.md +5 -5
- package/TROUBLESHOOTING.md +35 -14
- package/action.yml +12 -4
- package/audit/README.md +84 -0
- package/audit/audit-checklist.md +152 -0
- package/audit/boundary-selftest.sh +85 -0
- package/audit/boundary.sh +123 -0
- package/audit/count-hooks.py +42 -0
- package/audit/find-dead-hooks.sh +82 -0
- package/audit/find-unfirable-rules.sh +142 -0
- package/audit/fire.sh +97 -0
- package/audit/selftest.sh +42 -0
- package/audit/unfirable-selftest.sh +81 -0
- package/audit-web/index.html +9 -9
- package/examples/README.md +54 -17
- package/examples/account-billing-log.sh +98 -0
- package/examples/account-routing-preflight.sh +123 -0
- package/examples/agent-sdk-credit-pool-monitor.sh +145 -0
- package/examples/agent-view-quota-decrement.sh +32 -0
- package/examples/agent-view-quota-warn.sh +94 -0
- package/examples/agents-md-edit-drift-warner.sh +223 -0
- package/examples/agents-md-loader.sh +160 -0
- package/examples/agents-md-sync-checker.sh +102 -0
- package/examples/ai-slop-punctuation-arrest.sh +210 -0
- package/examples/allowlist.sh +70 -10
- package/examples/always-allow-pattern-suggester.sh +125 -0
- package/examples/ansible-vault-guard.sh +2 -1
- package/examples/anthropic-base-url-guard.sh +76 -0
- package/examples/api-busyloop-guard.sh +123 -0
- package/examples/api-endpoint-guard.sh +12 -0
- package/examples/api-key-in-url-guard.sh +17 -1
- package/examples/api-rate-limit-guard.sh +36 -1
- package/examples/api-rate-limit-tracker.sh +12 -0
- package/examples/articulated-scope-capture.sh +101 -0
- package/examples/askuserquestion-autonomy-gate.sh +102 -0
- package/examples/attachment-traversal-guard.sh +118 -0
- package/examples/aup-block-pattern-logger.sh +161 -0
- package/examples/aup-false-positive-helper.sh +124 -0
- package/examples/aup-large-tool-output-warner.sh +282 -0
- package/examples/aup-retry-loop-guard.sh +229 -0
- package/examples/auth-expiry-reminder.sh +157 -0
- package/examples/auth-macos-sleep-detector.sh +185 -0
- package/examples/auth-path-detector.sh +171 -0
- package/examples/auth-status-checker.sh +157 -0
- package/examples/authorized-reconfirmation-detector.sh +195 -0
- package/examples/auto-approve-build.sh +39 -0
- package/examples/auto-approve-cargo.sh +31 -1
- package/examples/auto-approve-docker.sh +35 -0
- package/examples/auto-approve-git-read.sh +37 -14
- package/examples/auto-approve-go.sh +30 -1
- package/examples/auto-approve-gradle.sh +29 -1
- package/examples/auto-approve-make.sh +29 -1
- package/examples/auto-approve-maven.sh +29 -1
- package/examples/auto-approve-python.sh +41 -1
- package/examples/auto-approve-readonly-tools.sh +1 -0
- package/examples/auto-approve-readonly.sh +110 -33
- package/examples/auto-approve-ssh.sh +30 -1
- package/examples/auto-approve-test.sh +44 -0
- package/examples/auto-checkpoint.sh +1 -1
- package/examples/auto-compact-prep.sh +0 -0
- package/examples/auto-git-checkpoint.sh +0 -0
- package/examples/auto-mode-safe-commands.sh +53 -1
- package/examples/auto-mode-safety-enforcer.sh +151 -4
- package/examples/auto-push-session-branch.sh +22 -0
- package/examples/aws-production-guard.sh +13 -1
- package/examples/aws-region-guard.sh +1 -1
- package/examples/background-cost-launch-guard.sh +82 -0
- package/examples/background-task-guard.sh +12 -0
- package/examples/backup-before-refactor.sh +0 -0
- package/examples/banned-command-guard.sh +12 -0
- package/examples/bash-allowlist-secondary-check.sh +157 -0
- package/examples/bash-domain-allowlist.sh +12 -0
- package/examples/bash-fanout-bounded-rewriter.sh +191 -0
- package/examples/bash-heuristic-approver.sh +112 -10
- package/examples/bash-project-fence.sh +194 -0
- package/examples/bash-safety-auto-deny.sh +12 -0
- package/examples/bash-secret-output-detector.sh +44 -3
- package/examples/bash-trace-guard.sh +12 -0
- package/examples/bashrc-safety-check.sh +0 -0
- package/examples/bg-permission-prompt-warner.sh +182 -0
- package/examples/bg-task-cooldown-guard.sh +12 -0
- package/examples/binary-read-detector.sh +135 -0
- package/examples/binary-upload-guard.sh +12 -0
- package/examples/block-database-wipe.sh +35 -10
- package/examples/branch-name-check.sh +8 -3
- package/examples/branch-naming-convention.sh +0 -0
- package/examples/broad-find-guard.sh +12 -0
- package/examples/broad-prefix-session-trap-warner.sh +106 -0
- package/examples/bulk-file-delete-guard.sh +45 -0
- package/examples/bypass-mode-effective-verifier.sh +203 -0
- package/examples/cache-creation-drift-detector.sh +120 -0
- package/examples/cache-residue-detector.sh +195 -0
- package/examples/cache-tier-logger.sh +70 -0
- package/examples/cache-ttl-eviction-detector.sh +149 -0
- package/examples/cargo-publish-guard.sh +14 -1
- package/examples/case-insensitive-path-guard.sh +21 -2
- package/examples/case-sensitive-guard.sh +23 -2
- package/examples/cch-cache-guard.sh +0 -0
- package/examples/cch-sentinel-precommit-guard.sh +47 -0
- package/examples/check-abort-controller.sh +1 -1
- package/examples/check-accessibility.sh +0 -0
- package/examples/check-aria-labels.sh +0 -0
- package/examples/check-before-act-enforcer.sh +12 -0
- package/examples/check-charset-meta.sh +0 -0
- package/examples/check-cookie-flags.sh +0 -0
- package/examples/check-cors-config.sh +0 -0
- package/examples/check-csp-headers.sh +0 -0
- package/examples/check-csrf-protection.sh +0 -0
- package/examples/check-debounce.sh +1 -1
- package/examples/check-dependency-age.sh +0 -0
- package/examples/check-dependency-license.sh +0 -0
- package/examples/check-dockerfile-best-practice.sh +0 -0
- package/examples/check-error-boundaries.sh +0 -0
- package/examples/check-error-class.sh +1 -1
- package/examples/check-error-handling.sh +0 -0
- package/examples/check-error-logging.sh +1 -1
- package/examples/check-error-message.sh +0 -0
- package/examples/check-error-stack.sh +0 -0
- package/examples/check-favicon.sh +0 -0
- package/examples/check-git-hooks-compat.sh +0 -0
- package/examples/check-gitattributes.sh +0 -0
- package/examples/check-https-redirect.sh +0 -0
- package/examples/check-input-validation.sh +0 -0
- package/examples/check-lang-attribute.sh +0 -0
- package/examples/check-npm-scripts-exist.sh +0 -0
- package/examples/check-package-size.sh +0 -0
- package/examples/check-port-availability.sh +0 -0
- package/examples/check-promise-all.sh +1 -1
- package/examples/check-rate-limiting.sh +0 -0
- package/examples/check-return-types.sh +0 -0
- package/examples/check-semantic-versioning.sh +0 -0
- package/examples/check-suspense-fallback.sh +1 -1
- package/examples/check-test-exists.sh +0 -0
- package/examples/check-test-naming.sh +0 -0
- package/examples/check-timeout-cleanup.sh +1 -1
- package/examples/check-tls-version.sh +0 -0
- package/examples/check-unsubscribe.sh +1 -1
- package/examples/check-viewport-meta.sh +0 -0
- package/examples/check-worker-terminate.sh +1 -1
- package/examples/checkpoint-tamper-guard.sh +12 -0
- package/examples/chmod-guard.sh +12 -0
- package/examples/chown-guard.sh +24 -0
- package/examples/ci-workflow-guard.sh +6 -1
- package/examples/claim-verify-detector.sh +109 -0
- package/examples/claim-vs-caveat-checker.sh +77 -0
- package/examples/classifier-fallback-allow.sh +114 -40
- package/examples/claude-cache-gc.sh +1 -0
- package/examples/claude-code-version-pin-advisor.sh +183 -0
- package/examples/claude-md-reinjector.sh +129 -0
- package/examples/claude-md-size-monitor.sh +66 -0
- package/examples/claude-update-budget-guard.sh +123 -0
- package/examples/claude-update-smart.sh +113 -0
- package/examples/claudeignore-enforce-guard.sh +12 -0
- package/examples/claudemd-enforcer.sh +0 -0
- package/examples/claudemd-tool-prohibition.sh +128 -0
- package/examples/clear-command-confirm-guard.sh +32 -15
- package/examples/cli-config-pinning-detector.sh +162 -0
- package/examples/cliff-countdown-advisor.sh +96 -0
- package/examples/clipboard-secret-guard.sh +12 -0
- package/examples/closure-word-verify-gate.sh +150 -0
- package/examples/cloud-cli-guard.sh +39 -2
- package/examples/commit-all-scope-guard.sh +44 -0
- package/examples/commit-message-check.sh +1 -1
- package/examples/commit-message-quality.sh +6 -1
- package/examples/commitment-carry-forward-arrest.sh +361 -0
- package/examples/compact-alert-notification.sh +0 -0
- package/examples/compact-dispatch-watchdog.sh +149 -0
- package/examples/completion-claim-without-verification-detector.sh +207 -0
- package/examples/composer-guard.sh +12 -0
- package/examples/compound-bash-permission-resolver.sh +156 -0
- package/examples/compound-command-allow.sh +1 -1
- package/examples/compound-command-deny-enforcer.sh +183 -0
- package/examples/compound-inject-guard.sh +12 -0
- package/examples/concurrent-edit-lock.sh +12 -0
- package/examples/conflict-marker-guard.sh +12 -0
- package/examples/consecutive-error-breaker.sh +0 -0
- package/examples/console-log-count.sh +1 -0
- package/examples/context-compact-advisor.sh +29 -2
- package/examples/context-length-budget.sh +69 -0
- package/examples/context-threshold-alert.sh +12 -0
- package/examples/context-usage-drift-alert.sh +41 -13
- package/examples/conversation-history-guard.sh +12 -0
- package/examples/core-file-protect-guard.sh +12 -0
- package/examples/cors-star-warn.sh +0 -0
- package/examples/cost-incident-self-audit.sh +162 -0
- package/examples/cowork-claude-md-load-checker.sh +100 -0
- package/examples/cowork-fuse-staleness-watcher.sh +140 -0
- package/examples/cowork-hook-absence-warner.sh +167 -0
- package/examples/cowork-model-picker-advisor.sh +115 -0
- package/examples/credential-exfil-guard.sh +65 -4
- package/examples/credential-file-cat-guard.sh +17 -1
- package/examples/cron-create-receipt.sh +112 -0
- package/examples/cron-modification-guard.sh +12 -0
- package/examples/cross-product-mcp-spawn-detector.sh +178 -0
- package/examples/cwd-project-boundary-guard.sh +0 -0
- package/examples/daemon-zombie-worker-surfacer.sh +118 -0
- package/examples/daily-cost-guard.sh +164 -0
- package/examples/daily-usage-tracker.sh +0 -0
- package/examples/dangerous-pip-flag-guard.sh +12 -0
- package/examples/db-connect-guard.sh +13 -1
- package/examples/denied-action-retry-guard.sh +12 -0
- package/examples/deny-bypass-detector.sh +12 -0
- package/examples/deny-rule-integrity-verifier.sh +181 -0
- package/examples/dependency-install-guard.sh +12 -0
- package/examples/deploy-guard.sh +14 -2
- package/examples/deploy-path-verify-guard.sh +12 -0
- package/examples/deployment-readback-gate.sh +135 -0
- package/examples/deployment-readback-gh-adapter.sh +247 -0
- package/examples/deployment-verify-guard.sh +25 -2
- package/examples/destructive-db-script-write-guard.sh +166 -0
- package/examples/destructive-migration-write-guard.sh +163 -0
- package/examples/diff-size-guard.sh +12 -0
- package/examples/disabled-feature-toggle-advisor.sh +88 -0
- package/examples/disk-partition-guard.sh +12 -0
- package/examples/dispatch-allowlist-preflight.sh +301 -0
- package/examples/dispatch-liveness-watchdog.sh +216 -0
- package/examples/dispatch-receipt.sh +174 -0
- package/examples/django-migrate-guard.sh +12 -0
- package/examples/dns-config-guard.sh +12 -0
- package/examples/docker-dangerous-guard.sh +12 -0
- package/examples/docker-volume-guard.sh +0 -0
- package/examples/dockerfile-latest-guard.sh +1 -0
- package/examples/dotenv-anthropic-key-billing-guard.sh +99 -0
- package/examples/dotenv-commit-guard.sh +12 -0
- package/examples/dotenv-read-guard.sh +12 -0
- package/examples/dotfile-protection-guard.sh +12 -0
- package/examples/dotnet-build-on-edit.sh +1 -1
- package/examples/drizzle-migrate-guard.sh +27 -2
- package/examples/echo-probe-spam-detector.sh +176 -0
- package/examples/edit-counter-test-gate.sh +12 -0
- package/examples/edit-error-counter.sh +1 -1
- package/examples/edit-guard.sh +12 -0
- package/examples/edit-old-string-validator.sh +12 -0
- package/examples/edit-quote-ambiguity-guard.sh +97 -0
- package/examples/edit-retry-loop-guard.sh +0 -0
- package/examples/edit-verify.sh +0 -0
- package/examples/env-inline-secret-guard.sh +14 -2
- package/examples/env-naming-convention.sh +0 -0
- package/examples/env-prod-guard.sh +0 -0
- package/examples/env-required-check.sh +0 -0
- package/examples/env-source-guard.sh +12 -0
- package/examples/env-var-check.sh +24 -1
- package/examples/ephemeral-container-detector.sh +147 -0
- package/examples/error-memory-guard.sh +12 -0
- package/examples/evidence-claim-gate.sh +187 -0
- package/examples/exploration-budget-guard.sh +12 -0
- package/examples/expo-eject-guard.sh +13 -0
- package/examples/extended-thinking-loop-guard.sh +139 -0
- package/examples/extended-thinking-resume-warning.sh +119 -0
- package/examples/extended-thinking-tool-use-mismatch-detector.sh +212 -0
- package/examples/fabricated-command-detector.sh +145 -0
- package/examples/false-disk-full-guard.sh +63 -0
- package/examples/feature-deprecation-detector.sh +109 -0
- package/examples/file-change-tracker.sh +1 -1
- package/examples/file-change-undo-tracker.sh +0 -0
- package/examples/file-edit-backup.sh +63 -14
- package/examples/file-reference-check.sh +0 -0
- package/examples/file-size-limit.sh +12 -0
- package/examples/financial-operation-guard.sh +12 -0
- package/examples/firewall-guard.sh +12 -0
- package/examples/fish-shell-wrapper.sh +125 -7
- package/examples/five-hundred-milestone.sh +1 -0
- package/examples/flask-static-route-guard.sh +89 -0
- package/examples/forbidden-response-phrase-detector.sh +161 -0
- package/examples/gem-push-guard.sh +13 -0
- package/examples/gh-cli-destructive-guard.sh +13 -1
- package/examples/git-checkout-safety-guard.sh +12 -0
- package/examples/git-checkout-uncommitted-guard.sh +12 -0
- package/examples/git-config-guard.sh +12 -0
- package/examples/git-crypt-worktree-guard.sh +12 -0
- package/examples/git-filter-repo-guard.sh +56 -0
- package/examples/git-history-rewrite-guard.sh +12 -0
- package/examples/git-hook-bypass-guard.sh +0 -0
- package/examples/git-maintenance-guard.sh +83 -0
- package/examples/git-merge-conflict-prevent.sh +0 -0
- package/examples/git-message-length-check.sh +0 -0
- package/examples/git-message-length.sh +0 -0
- package/examples/git-operations-require-approval.sh +68 -14
- package/examples/git-pack-temp-cleanup-guard.sh +102 -0
- package/examples/git-push-blast-radius-guard.sh +218 -0
- package/examples/git-remote-guard.sh +24 -3
- package/examples/git-rm-orphan-wipe-guard.sh +85 -0
- package/examples/git-stash-before-checkout.sh +12 -0
- package/examples/git-stash-before-danger.sh +0 -0
- package/examples/git-submodule-guard.sh +69 -2
- package/examples/git-tag-guard.sh +12 -0
- package/examples/github-actions-secret-guard.sh +0 -0
- package/examples/gitignore-check.sh +0 -0
- package/examples/gitops-drift-guard.sh +12 -0
- package/examples/go-mod-tidy-warn.sh +1 -0
- package/examples/go-vet-after-edit.sh +12 -0
- package/examples/goal-iteration-limit-warner.sh +152 -0
- package/examples/grep-nul-false-negative-guard.sh +30 -0
- package/examples/growthbook-flag-monitor.sh +257 -0
- package/examples/hallucination-url-check.sh +1 -1
- package/examples/halt-signal-detector.sh +135 -0
- package/examples/handoff-on-clear.sh +65 -0
- package/examples/hardcoded-ip-guard.sh +1 -0
- package/examples/headless-empty-result-guard.sh +0 -0
- package/examples/headless-stop-guard.sh +0 -0
- package/examples/helm-install-guard.sh +2 -1
- package/examples/home-critical-bash-guard.sh +17 -1
- package/examples/hook-debug-wrapper.sh +6 -2
- package/examples/hook-permission-fixer.sh +0 -0
- package/examples/hook-self-disable-detector.sh +99 -0
- package/examples/hook-stdout-sanitizer.sh +6 -2
- package/examples/hook-tamper-guard.sh +12 -0
- package/examples/idle-session-cost-alert.sh +0 -0
- package/examples/image-dimension-guard.sh +109 -0
- package/examples/image-file-validator.sh +0 -0
- package/examples/iteration-quality-degradation-detector.sh +170 -0
- package/examples/java-compile-on-edit.sh +1 -1
- package/examples/json-syntax-check.sh +0 -0
- package/examples/k8s-production-guard.sh +13 -1
- package/examples/kill-process-guard.sh +12 -0
- package/examples/kubernetes-guard.sh +13 -1
- package/examples/laravel-artisan-guard.sh +13 -0
- package/examples/large-file-guard.sh +1 -1
- package/examples/log-level-guard.sh +0 -0
- package/examples/log-truncation-guard.sh +12 -0
- package/examples/long-session-malformed-tool-call-detector.sh +183 -0
- package/examples/loop-detector.sh +12 -0
- package/examples/magic-number-warn.sh +1 -0
- package/examples/main-branch-warn.sh +12 -0
- package/examples/markdown-link-check.sh +0 -0
- package/examples/max-concurrent-agents.sh +12 -0
- package/examples/max-edit-size-guard.sh +13 -0
- package/examples/max-file-count-guard.sh +0 -0
- package/examples/max-file-delete-count.sh +0 -0
- package/examples/max-function-length.sh +1 -0
- package/examples/max-import-count.sh +0 -0
- package/examples/max-subagent-count.sh +0 -0
- package/examples/mcp-config-freeze.sh +12 -0
- package/examples/mcp-config-poisoning-audit.sh +150 -0
- package/examples/mcp-data-boundary.sh +1 -1
- package/examples/mcp-misdiagnosis-arrest.sh +209 -0
- package/examples/mcp-orphan-leak-warner.sh +49 -0
- package/examples/mcp-permissions-ask-warner.sh +151 -0
- package/examples/mcp-routine-approval-detector.sh +154 -0
- package/examples/mcp-server-allowlist.sh +12 -0
- package/examples/mcp-server-guard.sh +12 -0
- package/examples/mcp-startup-bloat-detector.sh +87 -0
- package/examples/mcp-stdio-compatibility-test.sh +153 -0
- package/examples/mcp-tool-audit-log.sh +0 -0
- package/examples/mcp-tool-guard.sh +101 -1
- package/examples/mcp-warmup-wait.sh +0 -0
- package/examples/memory-chain-audit.sh +56 -0
- package/examples/memory-orphan-detector.sh +188 -0
- package/examples/memory-write-guard.sh +99 -17
- package/examples/migration-verify-guard.sh +12 -0
- package/examples/model-swap-suggester.sh +177 -0
- package/examples/model-version-alert.sh +5 -1
- package/examples/model-version-lock.sh +63 -0
- package/examples/move-delete-sequence-guard.sh +33 -2
- package/examples/multi-file-plan-routing-gate.sh +192 -0
- package/examples/multi-vendor-concurrent-warner.sh +108 -0
- package/examples/multi-window-auth-drift-detector.sh +183 -0
- package/examples/multiline-command-approver.sh +161 -23
- package/examples/nested-background-agent-guard.sh +109 -0
- package/examples/nested-spawn-inflight-guard.sh +178 -0
- package/examples/network-exfil-guard.sh +12 -0
- package/examples/network-guard.sh +12 -0
- package/examples/network-interface-guard.sh +12 -0
- package/examples/nextjs-env-guard.sh +1 -1
- package/examples/no-absolute-import.sh +0 -0
- package/examples/no-alert-confirm-prompt.sh +0 -0
- package/examples/no-anonymous-default-export.sh +0 -0
- package/examples/no-any-type.sh +0 -0
- package/examples/no-any-typescript.sh +1 -0
- package/examples/no-ask-human.sh +12 -0
- package/examples/no-assignment-in-condition.sh +0 -0
- package/examples/no-base64-exfil.sh +12 -0
- package/examples/no-callback-hell.sh +0 -0
- package/examples/no-circular-dependency.sh +0 -0
- package/examples/no-cleartext-storage.sh +0 -0
- package/examples/no-commented-code.sh +0 -0
- package/examples/no-commit-fixup.sh +0 -0
- package/examples/no-console-assert.sh +0 -0
- package/examples/no-console-error-swallow.sh +0 -0
- package/examples/no-console-in-prod.sh +0 -0
- package/examples/no-console-log-commit.sh +12 -0
- package/examples/no-console-log.sh +0 -0
- package/examples/no-console-time.sh +0 -0
- package/examples/no-cors-wildcard.sh +4 -1
- package/examples/no-curl-upload.sh +0 -0
- package/examples/no-dangerouslySetInnerHTML.sh +0 -0
- package/examples/no-dangling-await.sh +1 -0
- package/examples/no-debug-commit.sh +12 -0
- package/examples/no-debug-in-commit.sh +0 -0
- package/examples/no-deep-nesting.sh +0 -0
- package/examples/no-deep-relative-import.sh +1 -0
- package/examples/no-default-credentials.sh +0 -0
- package/examples/no-deploy-friday.sh +13 -1
- package/examples/no-disabled-test.sh +0 -0
- package/examples/no-document-write.sh +0 -0
- package/examples/no-empty-function.sh +0 -0
- package/examples/no-eval-in-template.sh +0 -0
- package/examples/no-eval-template.sh +3 -1
- package/examples/no-eval.sh +0 -0
- package/examples/no-exec-user-input.sh +0 -0
- package/examples/no-fixme-ship.sh +12 -0
- package/examples/no-floating-promises.sh +0 -0
- package/examples/no-force-flag.sh +22 -5
- package/examples/no-force-install.sh +0 -0
- package/examples/no-git-amend.sh +12 -0
- package/examples/no-git-rebase-public.sh +0 -0
- package/examples/no-global-install.sh +12 -0
- package/examples/no-global-state.sh +0 -0
- package/examples/no-hardcoded-port.sh +1 -0
- package/examples/no-hardcoded-url.sh +0 -0
- package/examples/no-helmet-missing.sh +0 -0
- package/examples/no-http-url.sh +1 -0
- package/examples/no-http-without-https.sh +0 -0
- package/examples/no-inline-style.sh +0 -0
- package/examples/no-inline-styles.sh +1 -0
- package/examples/no-innerhtml.sh +0 -0
- package/examples/no-install-global.sh +12 -0
- package/examples/no-jwt-in-url.sh +0 -0
- package/examples/no-large-commit.sh +0 -0
- package/examples/no-localhost-expose.sh +0 -0
- package/examples/no-magic-number.sh +0 -0
- package/examples/no-md5-sha1.sh +0 -0
- package/examples/no-mixed-line-endings.sh +8 -1
- package/examples/no-mutation-in-reducer.sh +0 -0
- package/examples/no-nested-ternary.sh +0 -0
- package/examples/no-network-exfil.sh +0 -0
- package/examples/no-open-redirect.sh +0 -0
- package/examples/no-output-truncation.sh +12 -0
- package/examples/no-package-downgrade.sh +0 -0
- package/examples/no-package-lock-edit.sh +12 -0
- package/examples/no-path-join-user-input.sh +0 -0
- package/examples/no-port-bind.sh +0 -0
- package/examples/no-process-exit.sh +0 -0
- package/examples/no-prototype-pollution.sh +0 -0
- package/examples/no-push-without-ci.sh +0 -0
- package/examples/no-push-without-tests.sh +12 -0
- package/examples/no-raw-password-in-url.sh +0 -0
- package/examples/no-root-user-docker.sh +1 -0
- package/examples/no-root-write.sh +12 -0
- package/examples/no-secrets-in-args.sh +4 -1
- package/examples/no-secrets-in-logs.sh +0 -0
- package/examples/no-sensitive-log.sh +0 -0
- package/examples/no-sleep-in-hooks.sh +0 -0
- package/examples/no-star-import-python.sh +1 -0
- package/examples/no-string-concat-sql.sh +0 -0
- package/examples/no-sudo-guard.sh +12 -0
- package/examples/no-sync-fs.sh +0 -0
- package/examples/no-todo-in-merge.sh +0 -0
- package/examples/no-todo-in-production.sh +1 -0
- package/examples/no-todo-without-issue.sh +0 -0
- package/examples/no-unused-import.sh +0 -0
- package/examples/no-var-keyword.sh +0 -0
- package/examples/no-verify-blocker.sh +12 -0
- package/examples/no-wget-piped-bash.sh +12 -0
- package/examples/no-wildcard-cors.sh +0 -0
- package/examples/no-wildcard-delete.sh +0 -0
- package/examples/no-wildcard-import.sh +0 -0
- package/examples/no-with-statement.sh +0 -0
- package/examples/no-write-outside-src.sh +0 -0
- package/examples/no-xml-external-entity.sh +0 -0
- package/examples/non-english-quality-warner.sh +156 -0
- package/examples/notify-waiting.sh +1 -1
- package/examples/npm-audit-warn.sh +0 -0
- package/examples/npm-global-install-guard.sh +12 -0
- package/examples/npm-publish-guard.sh +12 -0
- package/examples/npm-script-injection.sh +0 -0
- package/examples/npm-supply-chain-guard.sh +0 -0
- package/examples/nuxt-config-guard.sh +1 -0
- package/examples/oauth-refresh-monitor.sh +210 -0
- package/examples/opus-degradation-tracker.sh +187 -0
- package/examples/opus48-routine-task-warning.sh +196 -0
- package/examples/opus48-thinking-wedge-advisor.sh +143 -0
- package/examples/output-credential-scan.sh +1 -1
- package/examples/output-secret-mask.sh +31 -9
- package/examples/output-token-spike-detector.sh +145 -0
- package/examples/package-json-guard.sh +12 -0
- package/examples/package-lock-frozen.sh +12 -0
- package/examples/parallel-batch-size-limiter.sh +121 -0
- package/examples/parallel-cascade-detector.sh +116 -0
- package/examples/partial-view-claim-arrest.sh +174 -0
- package/examples/path-deny-bash-guard.sh +12 -0
- package/examples/path-traversal-guard.sh +12 -0
- package/examples/per-prompt-token-cap.sh +124 -0
- package/examples/permission-audit-log.sh +1 -1
- package/examples/permission-denial-enforcer.sh +12 -0
- package/examples/permission-entry-validator.sh +0 -0
- package/examples/persisted-1m-model-advisor.sh +88 -0
- package/examples/php-lint-on-edit.sh +1 -1
- package/examples/pii-upload-guard.sh +12 -0
- package/examples/pip-publish-guard.sh +13 -0
- package/examples/pip-requirements-guard.sh +12 -0
- package/examples/pip-venv-required.sh +12 -0
- package/examples/plan-mode-edit-guard.sh +12 -0
- package/examples/plan-mode-enforcer.sh +12 -0
- package/examples/plan-mode-strict-guard.sh +12 -0
- package/examples/plugin-hooks-json-bloat-detector.sh +169 -0
- package/examples/plugin-process-cleanup.sh +0 -0
- package/examples/polyglot-rm-guard.sh +12 -0
- package/examples/post-compact-safety.sh +12 -0
- package/examples/post-edit-disk-verify.sh +152 -0
- package/examples/powershell-remove-item-guard.sh +85 -0
- package/examples/pr-description-check.sh +0 -0
- package/examples/pr-duplicate-guard.sh +13 -0
- package/examples/pre-bash-sed-line-ending-windows.sh +87 -0
- package/examples/pre-compact-knowledge-save.sh +0 -0
- package/examples/pre-compact-transcript-backup.sh +0 -0
- package/examples/pre-execution-claim-detector.sh +179 -0
- package/examples/prefer-builtin-tools.sh +10 -1
- package/examples/prefer-const.sh +0 -0
- package/examples/prefer-dedicated-tools.sh +12 -0
- package/examples/prefer-optional-chaining.sh +0 -0
- package/examples/prisma-migrate-guard.sh +24 -7
- package/examples/production-port-kill-guard.sh +12 -0
- package/examples/prompt-injection-guard.sh +2 -1
- package/examples/prompt-usage-logger.sh +0 -0
- package/examples/protect-claudemd.sh +12 -0
- package/examples/protect-dotfiles.sh +12 -0
- package/examples/proxy-capture-suggester.sh +159 -0
- package/examples/public-artefact-socratic-narrowing.sh +232 -0
- package/examples/public-repo-push-guard.sh +12 -0
- package/examples/push-requires-test-pass-record.sh +0 -0
- package/examples/push-requires-test-pass.sh +12 -0
- package/examples/quota-anomaly-detector.sh +173 -0
- package/examples/quota-reset-audit.sh +58 -0
- package/examples/quoted-flag-approver.sh +99 -10
- package/examples/rails-migration-guard.sh +12 -0
- package/examples/rate-limit-guard.sh +0 -0
- package/examples/read-all-files-enforcer.sh +0 -0
- package/examples/read-budget-guard.sh +12 -0
- package/examples/read-loop-detector.sh +59 -0
- package/examples/read-once-guard.sh +96 -0
- package/examples/read-only-mode.sh +12 -0
- package/examples/readme-exists-check.sh +0 -0
- package/examples/record-read-coverage.sh +73 -0
- package/examples/redirect-fragment-warner.sh +149 -0
- package/examples/redis-flushall-guard.sh +13 -0
- package/examples/redundant-read-blocker.sh +132 -0
- package/examples/refusal-arrest-gate.sh +248 -0
- package/examples/registry-publish-guard.sh +13 -1
- package/examples/remote-control-billing-classifier.sh +135 -0
- package/examples/replace-all-guard.sh +12 -0
- package/examples/repo-visibility-guard.sh +12 -0
- package/examples/reroute-after-block-guard.sh +150 -0
- package/examples/response-budget-guard.sh +0 -0
- package/examples/resume-drift-watcher.sh +57 -0
- package/examples/rg-replace-flag-detector.sh +125 -0
- package/examples/rhetorical-verification-prompt-detector.sh +102 -0
- package/examples/ripgrep-permission-fix.sh +0 -0
- package/examples/rm-safety-net.sh +151 -8
- package/examples/role-tool-guard.sh +12 -0
- package/examples/route-handler-emptiness-gate.sh +324 -0
- package/examples/ruby-lint-on-edit.sh +1 -1
- package/examples/runtime-binary-change-detector.sh +102 -0
- package/examples/same-command-repeat-detector.sh +196 -0
- package/examples/same-correction-arrest.sh +169 -0
- package/examples/sandbox-denywrite-enforcer.sh +78 -0
- package/examples/sandbox-relative-path-audit.sh +83 -25
- package/examples/sandbox-write-verify.sh +12 -0
- package/examples/schema-migration-guard.sh +0 -0
- package/examples/scope-expansion-receipt.sh +178 -0
- package/examples/scope-guard.sh +88 -9
- package/examples/secret-file-read-guard.sh +12 -0
- package/examples/secret-file-write-guard.sh +150 -0
- package/examples/self-modify-bypass-guard.sh +0 -0
- package/examples/sensitive-file-read-guard.sh +23 -3
- package/examples/sensitive-log-guard.sh +1 -0
- package/examples/server-side-prompt-injection-detector.sh +69 -0
- package/examples/session-agent-cost-limiter.sh +12 -0
- package/examples/session-backup-on-start.sh +1 -1
- package/examples/session-cost-alert.sh +12 -0
- package/examples/session-drift-guard.sh +12 -0
- package/examples/session-duration-guard.sh +25 -2
- package/examples/session-end-logger.sh +0 -0
- package/examples/session-health-monitor.sh +0 -0
- package/examples/session-index-repair.sh +1 -1
- package/examples/session-memory-watchdog.sh +1 -0
- package/examples/session-permission-reset-guard.sh +12 -0
- package/examples/session-persistence-verifier.sh +93 -0
- package/examples/session-plugin-pin-watch.sh +68 -0
- package/examples/session-rate-monitor.sh +176 -0
- package/examples/session-resume-env-fix.sh +0 -0
- package/examples/session-start-quota-status.sh +193 -0
- package/examples/session-start-safety-check.sh +55 -3
- package/examples/session-state-saver.sh +0 -0
- package/examples/session-summary-stop.sh +1 -1
- package/examples/session-summary.sh +0 -0
- package/examples/session-token-counter.sh +1 -1
- package/examples/settings-hooks-key-restorer.sh +99 -0
- package/examples/settings-json-health-check.sh +57 -0
- package/examples/settings-json-model-guard.sh +0 -0
- package/examples/settings-regression-tester.sh +188 -0
- package/examples/shell-config-truncation-guard.sh +12 -0
- package/examples/shell-wrapper-guard.sh +12 -0
- package/examples/skill-cumulative-size-detector.sh +104 -0
- package/examples/skill-description-drop-detector.sh +148 -0
- package/examples/skill-gate.sh +0 -0
- package/examples/skill-truncation-detector.sh +154 -0
- package/examples/skills-context-recorder.sh +167 -0
- package/examples/skills-load-verifier.sh +96 -0
- package/examples/skills-settings-validator.sh +139 -0
- package/examples/sonnet-45-deprecation-helper.sh +85 -0
- package/examples/spec-file-scope-guard.sh +12 -0
- package/examples/spring-profile-guard.sh +1 -0
- package/examples/spurious-malformed-notice-detector.sh +247 -0
- package/examples/sql-bulk-delete-warn.sh +88 -0
- package/examples/sql-injection-detect.sh +0 -0
- package/examples/ssh-key-protect.sh +12 -0
- package/examples/staged-secret-scan.sh +22 -1
- package/examples/stale-temp-settings-detector.sh +86 -0
- package/examples/standing-rule-session-surfacer.sh +137 -0
- package/examples/stop-hook-sigterm-wrapper.sh +182 -0
- package/examples/stop-transcript-write-health.sh +64 -0
- package/examples/strict-allowlist.sh +57 -15
- package/examples/strip-coauthored-by.sh +50 -10
- package/examples/subagent-blast-radius-guard.sh +184 -0
- package/examples/subagent-boundary-precheck.sh +126 -0
- package/examples/subagent-budget-guard.sh +12 -0
- package/examples/subagent-claudemd-inject.sh +0 -0
- package/examples/subagent-closure-verify-gate.sh +164 -0
- package/examples/subagent-destructive-git-guard.sh +120 -0
- package/examples/subagent-error-detector.sh +0 -0
- package/examples/subagent-forged-system-reminder-guard.sh +156 -0
- package/examples/subagent-identity-leak-guard.sh +102 -0
- package/examples/subagent-identity-reassertion.sh +51 -0
- package/examples/subagent-inheritance-tester.sh +179 -0
- package/examples/subagent-permission-mode-guard.sh +110 -0
- package/examples/subagent-scope-guard.sh +12 -0
- package/examples/subagent-spawn-verification-enforcer.sh +102 -0
- package/examples/subagent-tool-allowlist-enforcer.sh +101 -0
- package/examples/subagent-tool-call-limiter.sh +87 -15
- package/examples/subcommand-chain-guard.sh +12 -0
- package/examples/subscription-api-billing-warner.sh +160 -0
- package/examples/subscription-bypass-detector.sh +152 -0
- package/examples/svelte-lint-on-edit.sh +1 -0
- package/examples/swift-build-on-edit.sh +1 -1
- package/examples/symlink-guard.sh +27 -2
- package/examples/symlink-protect.sh +1 -0
- package/examples/system-dir-protection-guard.sh +73 -8
- package/examples/system-message-workaround.sh +38 -13
- package/examples/system-package-guard.sh +12 -0
- package/examples/systemd-service-guard.sh +12 -0
- package/examples/task-integrity-guard.sh +12 -0
- package/examples/temp-file-cleanup.sh +1 -1
- package/examples/temporal-suggestion-detector.sh +135 -0
- package/examples/terraform-guard.sh +27 -6
- package/examples/test-after-edit.sh +1 -1
- package/examples/test-before-push.sh +12 -0
- package/examples/test-coverage-reminder.sh +24 -1
- package/examples/thinking-budget-effort-mismatch-detector.sh +149 -0
- package/examples/timezone-guard.sh +0 -0
- package/examples/tmp-output-size-guard.sh +0 -0
- package/examples/todo-check.sh +1 -1
- package/examples/token-budget-guard.sh +12 -0
- package/examples/token-budget-per-task.sh +12 -0
- package/examples/token-usage-tracker.sh +7 -1
- package/examples/tokenizer-ratio-alert-corpus.sh +90 -0
- package/examples/tokenizer-ratio-alert.sh +104 -0
- package/examples/tool-call-rate-limiter.sh +0 -0
- package/examples/tool-result-correlation-checker.sh +167 -0
- package/examples/tool-result-size-guard.sh +132 -0
- package/examples/tool-retry-budget-guard.sh +12 -0
- package/examples/transcript-contamination-detector.sh +138 -0
- package/examples/trustfall-mcp-injection-guard.sh +103 -0
- package/examples/ultrareview-large-diff-advisor.sh +184 -0
- package/examples/unbounded-output-guard.sh +94 -0
- package/examples/uncommitted-changes-stop.sh +1 -0
- package/examples/uncommitted-discard-guard.sh +23 -5
- package/examples/uncommitted-work-guard.sh +12 -0
- package/examples/usage-warn.sh +0 -0
- package/examples/user-account-guard.sh +12 -0
- package/examples/userprompt-submit-receipt.sh +123 -0
- package/examples/variable-expansion-guard.sh +12 -0
- package/examples/verify-after-publish-reminder.sh +93 -0
- package/examples/verify-before-commit.sh +12 -0
- package/examples/version-bump-detector.sh +156 -0
- package/examples/version-regression-warner.sh +144 -0
- package/examples/vue-lint-on-edit.sh +1 -0
- package/examples/warn-cron-cost-trap.sh +173 -0
- package/examples/webfetch-runaway-guard.sh +89 -0
- package/examples/wellness-break-reminder.sh +118 -0
- package/examples/windows-destructive-command-guard.sh +177 -0
- package/examples/windows-path-guard.sh +12 -0
- package/examples/windows-python-stub-detector.sh +63 -0
- package/examples/work-hours-guard.sh +12 -0
- package/examples/working-directory-fence.sh +12 -0
- package/examples/workspace-lease-guard.sh +205 -0
- package/examples/worktree-create-log.sh +1 -0
- package/examples/worktree-delete-guard.sh +12 -0
- package/examples/worktree-edit-boundary-guard.sh +127 -0
- package/examples/worktree-escape-write-guard.sh +114 -0
- package/examples/worktree-hook-linker.sh +0 -0
- package/examples/worktree-hooks-path-fix.sh +111 -0
- package/examples/worktree-parent-write-guard.sh +43 -0
- package/examples/worktree-project-unify.sh +2 -1
- package/examples/worktree-remove-uncommitted-guard.sh +13 -0
- package/examples/worktree-unmerged-guard.sh +7 -1
- package/examples/write-byte-integrity-verifier.sh +190 -0
- package/examples/write-empty-content-guard.sh +67 -0
- package/examples/write-nul-corruption-detector.sh +61 -0
- package/examples/write-overwrite-confirm.sh +160 -14
- package/examples/write-secret-guard.sh +27 -5
- package/examples/write-shrink-guard.sh +12 -0
- package/examples/write-test-ratio.sh +0 -0
- package/examples/wsl-host-disk-space-guard.sh +97 -0
- package/examples/xml-format-leak-detector.sh +266 -0
- package/examples/yaml-syntax-check.sh +12 -0
- package/hooks/hooks.json +6 -6
- package/index.mjs +1718 -183
- package/mission.md +2 -0
- package/package.json +4 -4
- package/plugins/credential-guard/.claude-plugin/plugin.json +9 -7
- package/plugins/git-protection/.claude-plugin/plugin.json +10 -8
- package/plugins/safety-essentials/.claude-plugin/plugin.json +9 -7
- package/plugins/token-guard/.claude-plugin/plugin.json +10 -8
- package/scripts/agents-md-sync-setup.sh +156 -0
- package/scripts/autonomy-blocked-summary.sh +148 -0
- package/scripts/build-search-index.py +43 -0
- package/scripts/build-sitemap.py +119 -0
- package/scripts/cc-doctor.sh +192 -0
- package/scripts/check-hook-event-names.py +127 -0
- package/scripts/check-misfire-instrument.sh +64 -0
- package/scripts/claim-verify-audit.sh +467 -0
- package/scripts/cowork-claudemd-helper.sh +136 -0
- package/scripts/june-15-deprecated-model-scan.sh +111 -0
- package/scripts/measure-heredoc-shapes.sh +67 -0
- package/scripts/measure-literal-match-misfire.sh +110 -0
- package/scripts/probe-scope-guard-branches.sh +48 -0
- package/scripts/probe-skip-line-both-ways.sh +65 -0
- package/scripts/receipts-aggregate.py +199 -0
- package/scripts/session-forensic-audit.py +360 -0
- package/scripts.json +9 -9
- package/scripts.json.bak-2026-07-27-find +13 -0
- package/skills/safety-setup/SKILL.md +5 -5
- package/tests/approve-side-remaining-two.test.sh +129 -0
- package/tests/approver-list-granularity.test.sh +145 -0
- package/tests/askuserquestion-autonomy-gate.test.sh +181 -0
- package/tests/audit-ci-gate.test.sh +87 -0
- package/tests/audit-cross-layer-claudemd.test.sh +170 -0
- package/tests/audit-fail-open-parse.test.sh +100 -0
- package/tests/auto-approve-compound-tail.test.sh +194 -0
- package/tests/auto-mode-path-invoked-commands.test.sh +89 -0
- package/tests/auto-mode-quoted-targets.test.sh +127 -0
- package/tests/auto-mode-unquoted-targets.test.sh +112 -0
- package/tests/bash-secret-output-detector-detects.test.sh +102 -0
- package/tests/blindspots-cross-layer.test.sh +177 -0
- package/tests/block-database-wipe.test.sh +64 -0
- package/tests/bundled-short-flags-bypass.test.sh +85 -0
- package/tests/cd-git-allow-compound-tail.test.sh +67 -0
- package/tests/chown-guard-filesystem-root.test.sh +64 -0
- package/tests/ci-workflow-guard-skip-rule.test.sh +115 -0
- package/tests/compound-deny-safe-rm-targets.test.sh +105 -0
- package/tests/core-scripts-parser-fallback.test.sh +140 -0
- package/tests/destructive-guard-bare-glob.test.sh +74 -0
- package/tests/destructive-guard-every-operand.test.sh +100 -0
- package/tests/destructive-guard-find-deletion.test.sh +114 -0
- package/tests/destructive-guard-flag-order.test.sh +106 -0
- package/tests/destructive-guard-mentions-vs-invocations.test.sh +107 -0
- package/tests/destructive-guard-quoted-target.test.sh +89 -0
- package/tests/destructive-guard-separators.test.sh +105 -0
- package/tests/destructive-guard-variable-target.test.sh +98 -0
- package/tests/destructive-guard-wrapped-command.test.sh +91 -0
- package/tests/doctor-hook-disabling-env.test.sh +92 -0
- package/tests/doctor-misspelled-settings-keys.test.sh +106 -0
- package/tests/example-guards-wrapped-command.test.sh +169 -0
- package/tests/file-edit-backup.test.sh +93 -0
- package/tests/git-filter-repo-guard.test.sh +60 -0
- package/tests/git-global-options-bypass.test.sh +141 -0
- package/tests/git-invocation-prefixes-all-guards.test.sh +114 -0
- package/tests/git-maintenance-guard.test.sh +83 -0
- package/tests/git-pack-temp-cleanup-guard.test.sh +133 -0
- package/tests/git-rm-orphan-wipe-guard.test.sh +66 -0
- package/tests/git-submodule-guard.test.sh +50 -0
- package/tests/grep-pcre-portability.test.sh +155 -0
- package/tests/hook-registration-matches-input.test.sh +73 -0
- package/tests/hook-trigger-matches-envelope.test.sh +178 -0
- package/tests/install-does-not-claim-protection.test.sh +110 -0
- package/tests/install-example-standalone-tools.test.sh +139 -0
- package/tests/line-continuation-bypass.test.sh +114 -0
- package/tests/mcp-config-poisoning-audit.test.sh +106 -0
- package/tests/nested-background-agent-guard.test.sh +58 -0
- package/tests/no-unqualified-safety-claims.test.sh +114 -0
- package/tests/option-eating-grep-patterns.test.sh +130 -0
- package/tests/outdated-core-guards.test.sh +134 -0
- package/tests/outdated-report.test.sh +155 -0
- package/tests/output-secret-mask-warns.test.sh +73 -0
- package/tests/plugin-hooks-fail-open-under-sh.test.sh +165 -0
- package/tests/plugins-word-order.test.sh +126 -0
- package/tests/powershell-remove-item-guard.test.sh +85 -0
- package/tests/project-dir-naming.test.sh +103 -0
- package/tests/quoted-safe-targets-and-mentions.test.sh +190 -0
- package/tests/reroute-after-block-guard.test.sh +104 -0
- package/tests/secret-guard-documented-promises.test.sh +97 -0
- package/tests/session-plugin-pin-watch.test.sh +45 -0
- package/tests/settings-unreadable-refuses-to-write.test.sh +95 -0
- package/tests/shield-no-silent-adoption.test.py +110 -0
- package/tests/shield-no-silent-adoption.test.sh +46 -0
- package/tests/stop-transcript-write-health.test.sh +46 -0
- package/tests/system-dir-guard-root-erased.test.sh +66 -0
- package/tests/test-account-billing-log.sh +100 -0
- package/tests/test-account-routing-preflight.sh +77 -0
- package/tests/test-agent-sdk-credit-pool-monitor.sh +157 -0
- package/tests/test-agent-view-quota-warn.sh +184 -0
- package/tests/test-agents-md-edit-drift-warner.sh +176 -0
- package/tests/test-agents-md-loader.sh +204 -0
- package/tests/test-agents-md-sync-checker.sh +125 -0
- package/tests/test-ai-slop-punctuation-arrest.sh +280 -0
- package/tests/test-allowlist.sh +60 -0
- package/tests/test-always-allow-pattern-suggester.sh +147 -0
- package/tests/test-anthropic-base-url-guard.sh +88 -0
- package/tests/test-articulated-scope-capture.sh +139 -0
- package/tests/test-attachment-traversal-guard.sh +168 -0
- package/tests/test-aup-block-pattern-logger.sh +315 -0
- package/tests/test-aup-false-positive-helper.sh +188 -0
- package/tests/test-aup-large-tool-output-warner.sh +370 -0
- package/tests/test-aup-retry-loop-guard.sh +341 -0
- package/tests/test-auth-expiry-reminder.sh +303 -0
- package/tests/test-auth-macos-sleep-detector.sh +254 -0
- package/tests/test-auth-path-detector.sh +232 -0
- package/tests/test-auth-status-checker.sh +233 -0
- package/tests/test-authorized-reconfirmation-detector.sh +280 -0
- package/tests/test-background-cost-launch-guard.sh +62 -0
- package/tests/test-bash-allowlist-secondary-check.sh +143 -0
- package/tests/test-bash-fanout-bounded-rewriter.sh +186 -0
- package/tests/test-bash-project-fence.sh +127 -0
- package/tests/test-bg-permission-prompt-warner.sh +221 -0
- package/tests/test-binary-read-detector.sh +173 -0
- package/tests/test-broad-prefix-session-trap-warner.sh +167 -0
- package/tests/test-bulk-delete-target-resolution.sh +49 -0
- package/tests/test-bypass-mode-effective-verifier.sh +179 -0
- package/tests/test-cache-creation-drift-detector.sh +244 -0
- package/tests/test-cache-residue-detector.sh +429 -0
- package/tests/test-cache-tier-logger.sh +59 -0
- package/tests/test-cache-ttl-eviction-detector.sh +282 -0
- package/tests/test-cch-sentinel-precommit-guard.sh +64 -0
- package/tests/test-claim-verify-detector.sh +222 -0
- package/tests/test-claim-vs-caveat-checker.sh +134 -0
- package/tests/test-claude-code-version-pin-advisor.sh +353 -0
- package/tests/test-claude-md-reinjector.sh +173 -0
- package/tests/test-claude-md-size-monitor.sh +107 -0
- package/tests/test-claude-update-budget-guard.sh +132 -0
- package/tests/test-claude-update-smart.sh +91 -0
- package/tests/test-claudemd-tool-prohibition.sh +239 -0
- package/tests/test-cli-config-pinning-detector.sh +233 -0
- package/tests/test-cliff-countdown-advisor.sh +138 -0
- package/tests/test-closure-word-verify-gate.sh +158 -0
- package/tests/test-commit-all-scope-guard.sh +73 -0
- package/tests/test-commitment-carry-forward-arrest.sh +250 -0
- package/tests/test-compact-dispatch-watchdog.sh +147 -0
- package/tests/test-completion-claim-without-verification-detector.sh +326 -0
- package/tests/test-compound-bash-permission-resolver.sh +264 -0
- package/tests/test-compound-command-deny-enforcer.sh +67 -0
- package/tests/test-context-length-budget.sh +68 -0
- package/tests/test-context-usage-drift-alert.sh +52 -22
- package/tests/test-cost-incident-self-audit.sh +94 -0
- package/tests/test-cowork-claude-md-load-checker.sh +257 -0
- package/tests/test-cowork-claudemd-helper.sh +141 -0
- package/tests/test-cowork-fuse-staleness-watcher.sh +287 -0
- package/tests/test-cowork-hook-absence-warner.sh +230 -0
- package/tests/test-cowork-model-picker-advisor.sh +317 -0
- package/tests/test-credential-exfil-guard.sh +62 -0
- package/tests/test-cron-create-receipt.sh +165 -0
- package/tests/test-cross-product-mcp-spawn-detector.sh +112 -0
- package/tests/test-daemon-zombie-worker-surfacer.sh +71 -0
- package/tests/test-daily-cost-guard.sh +131 -0
- package/tests/test-deny-rule-integrity-verifier.sh +288 -0
- package/tests/test-deployment-readback-gate.sh +92 -0
- package/tests/test-deployment-readback-gh-adapter.sh +163 -0
- package/tests/test-disabled-feature-toggle-advisor.sh +78 -0
- package/tests/test-dispatch-allowlist-preflight.sh +385 -0
- package/tests/test-dispatch-liveness-watchdog.sh +319 -0
- package/tests/test-dispatch-receipt.sh +314 -0
- package/tests/test-dotenv-anthropic-key-billing-guard.sh +160 -0
- package/tests/test-echo-probe-spam-detector.sh +143 -0
- package/tests/test-edit-quote-ambiguity-guard.sh +75 -0
- package/tests/test-ephemeral-container-detector.sh +251 -0
- package/tests/test-evidence-claim-gate.sh +291 -0
- package/tests/test-extended-thinking-loop-guard.sh +289 -0
- package/tests/test-extended-thinking-resume-warning.sh +240 -0
- package/tests/test-extended-thinking-tool-use-mismatch-detector.sh +236 -0
- package/tests/test-fabricated-command-detector.sh +296 -0
- package/tests/test-false-disk-full-guard.sh +36 -0
- package/tests/test-feature-deprecation-detector.sh +117 -0
- package/tests/test-forbidden-response-phrase-detector.sh +246 -0
- package/tests/test-git-operations-require-approval.sh +53 -0
- package/tests/test-git-push-blast-radius-guard.sh +115 -0
- package/tests/test-goal-iteration-limit-warner.sh +128 -0
- package/tests/test-growthbook-flag-monitor.sh +428 -0
- package/tests/test-halt-signal-detector.sh +120 -0
- package/tests/test-hook-self-disable-detector.sh +232 -0
- package/tests/test-iteration-quality-degradation-detector.sh +244 -0
- package/tests/test-long-session-malformed-tool-call-detector.sh +185 -0
- package/tests/test-marketplace-plugins.sh +193 -0
- package/tests/test-mcp-misdiagnosis-arrest.sh +235 -0
- package/tests/test-mcp-orphan-leak-warner.sh +71 -0
- package/tests/test-mcp-permissions-ask-warner.sh +207 -0
- package/tests/test-mcp-routine-approval-detector.sh +229 -0
- package/tests/test-mcp-startup-bloat-detector.sh +141 -0
- package/tests/test-mcp-stdio-compatibility-test.sh +112 -0
- package/tests/test-memory-chain-audit.sh +59 -0
- package/tests/test-memory-orphan-detector.sh +227 -0
- package/tests/test-model-swap-suggester.sh +368 -0
- package/tests/test-model-version-lock.sh +83 -0
- package/tests/test-multi-file-plan-routing-gate.sh +277 -0
- package/tests/test-multi-window-auth-drift-detector.sh +262 -0
- package/tests/test-nested-spawn-inflight-guard.sh +281 -0
- package/tests/test-no-force-flag.sh +49 -0
- package/tests/test-non-english-quality-warner.sh +229 -0
- package/tests/test-oauth-refresh-monitor.sh +311 -0
- package/tests/test-opus-degradation-tracker.sh +274 -0
- package/tests/test-opus48-routine-task-warning.sh +201 -0
- package/tests/test-opus48-thinking-wedge-advisor.sh +249 -0
- package/tests/test-output-token-spike-detector.sh +315 -0
- package/tests/test-parallel-batch-size-limiter.sh +228 -0
- package/tests/test-parallel-cascade-detector.sh +191 -0
- package/tests/test-partial-view-claim-arrest.sh +272 -0
- package/tests/test-per-prompt-token-cap.sh +136 -0
- package/tests/test-persisted-1m-model-advisor.sh +71 -0
- package/tests/test-plugin-hooks-json-bloat-detector.sh +267 -0
- package/tests/test-post-edit-disk-verify.sh +294 -0
- package/tests/test-pre-bash-sed-line-ending-windows.sh +108 -0
- package/tests/test-pre-execution-claim-detector.sh +366 -0
- package/tests/test-private-key-backup-and-git-credentials.sh +100 -0
- package/tests/test-proxy-capture-suggester.sh +214 -0
- package/tests/test-public-artefact-socratic-narrowing.sh +346 -0
- package/tests/test-quota-anomaly-detector.sh +321 -0
- package/tests/test-quota-reset-audit.sh +81 -0
- package/tests/test-read-loop-detector.sh +137 -0
- package/tests/test-read-once-guard.sh +85 -0
- package/tests/test-receipts-aggregate.sh +143 -0
- package/tests/test-redirect-fragment-warner.sh +130 -0
- package/tests/test-redundant-read-blocker.sh +155 -0
- package/tests/test-refusal-arrest-gate.sh +303 -0
- package/tests/test-remote-control-billing-classifier.sh +125 -0
- package/tests/test-resume-drift-watcher.sh +65 -0
- package/tests/test-rg-replace-flag-detector.sh +175 -0
- package/tests/test-rhetorical-verification-prompt-detector.sh +237 -0
- package/tests/test-rm-safety-net.sh +115 -0
- package/tests/test-route-handler-emptiness-gate.sh +300 -0
- package/tests/test-runtime-binary-change-detector.sh +196 -0
- package/tests/test-same-command-repeat-detector.sh +165 -0
- package/tests/test-same-correction-arrest.sh +165 -0
- package/tests/test-scope-expansion-receipt.sh +207 -0
- package/tests/test-server-side-prompt-injection-detector.sh +181 -0
- package/tests/test-session-persistence-verifier.sh +128 -0
- package/tests/test-session-rate-monitor.sh +284 -0
- package/tests/test-session-start-quota-status.sh +210 -0
- package/tests/test-session-start-safety-check.sh +138 -0
- package/tests/test-settings-hooks-key-restorer.sh +257 -0
- package/tests/test-settings-json-health-check.sh +70 -0
- package/tests/test-settings-regression-tester.sh +197 -0
- package/tests/test-skill-cumulative-size-detector.sh +198 -0
- package/tests/test-skill-description-drop-detector.sh +236 -0
- package/tests/test-skill-truncation-detector.sh +263 -0
- package/tests/test-skills-context-recorder.sh +329 -0
- package/tests/test-skills-load-verifier.sh +184 -0
- package/tests/test-skills-settings-validator.sh +242 -0
- package/tests/test-sonnet-45-deprecation-helper.sh +150 -0
- package/tests/test-spurious-malformed-notice-detector.sh +290 -0
- package/tests/test-sql-bulk-delete-warn.sh +123 -0
- package/tests/test-ssh-key-protect.sh +81 -0
- package/tests/test-stale-temp-settings-detector.sh +161 -0
- package/tests/test-standing-rule-session-surfacer.sh +215 -0
- package/tests/test-starter-hooks-manifest.sh +96 -0
- package/tests/test-stop-hook-sigterm-wrapper.sh +258 -0
- package/tests/test-strict-allowlist.sh +72 -0
- package/tests/test-subagent-boundary-precheck.sh +137 -0
- package/tests/test-subagent-closure-verify-gate.sh +193 -0
- package/tests/test-subagent-destructive-git-guard.sh +86 -0
- package/tests/test-subagent-identity-leak-guard.sh +62 -0
- package/tests/test-subagent-identity-reassertion.sh +61 -0
- package/tests/test-subagent-inheritance-tester.sh +319 -0
- package/tests/test-subagent-permission-mode-guard.sh +61 -0
- package/tests/test-subagent-spawn-verification-enforcer.sh +60 -0
- package/tests/test-subagent-tool-allowlist-enforcer.sh +62 -0
- package/tests/test-subagent-tool-call-limiter.sh +97 -0
- package/tests/test-subscription-api-billing-warner.sh +138 -0
- package/tests/test-subscription-bypass-detector.sh +255 -0
- package/tests/test-temporal-suggestion-detector.sh +183 -0
- package/tests/test-thinking-budget-effort-mismatch-detector.sh +327 -0
- package/tests/test-tokenizer-ratio-alert-corpus.sh +77 -0
- package/tests/test-tokenizer-ratio-alert.sh +93 -0
- package/tests/test-tool-result-correlation-checker.sh +264 -0
- package/tests/test-tool-result-size-guard.sh +121 -0
- package/tests/test-transcript-contamination-detector.sh +264 -0
- package/tests/test-trigger-header-parsing.sh +151 -0
- package/tests/test-ultrareview-large-diff-advisor.sh +192 -0
- package/tests/test-userprompt-submit-receipt.sh +181 -0
- package/tests/test-verify-after-publish-reminder.sh +184 -0
- package/tests/test-version-bump-detector.sh +212 -0
- package/tests/test-version-regression-warner.sh +165 -0
- package/tests/test-warn-cron-cost-trap.sh +82 -0
- package/tests/test-webfetch-runaway-guard.sh +77 -0
- package/tests/test-wellness-break-reminder.sh +138 -0
- package/tests/test-windows-destructive-command-guard.sh +169 -0
- package/tests/test-windows-python-stub-detector.sh +146 -0
- package/tests/test-worktree-edit-boundary-guard.sh +219 -0
- package/tests/test-write-byte-integrity-verifier.sh +192 -0
- package/tests/test-xml-format-leak-detector.sh +299 -0
- package/tests/trustfall-mcp-injection-guard.test.sh +183 -0
- package/tests/workspace-lease-guard.test.sh +144 -0
- package/tests/worktree-escape-write-guard.test.sh +68 -0
- package/tests/worktree-hooks-path-fix.test.sh +181 -0
- package/tests/worktree-parent-write-guard.test.sh +51 -0
- package/tests/write-empty-content-guard.test.sh +39 -0
- package/tests/write-nul-corruption-detector.test.sh +29 -0
- package/tests/write-overwrite-unread-content.test.sh +178 -0
- package/tests/wsl-host-disk-space-guard.test.sh +55 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# The five quoted targets auto-mode-safety-enforcer left alone, and the mentions
|
|
3
|
+
# that had to keep passing.
|
|
4
|
+
#
|
|
5
|
+
# PR #1008 closed eleven of nineteen gaps in that hook but stopped at the quoted
|
|
6
|
+
# forms, and said why in the file itself:
|
|
7
|
+
#
|
|
8
|
+
# Quoted forms ("/", "$HOME", ".git") are deliberately still not matched.
|
|
9
|
+
# This hook has no mention-vs-invocation pass, so putting a quote in a
|
|
10
|
+
# terminator set would also block `echo "rm -rf /"` and a commit message
|
|
11
|
+
# that names the command.
|
|
12
|
+
#
|
|
13
|
+
# That is now ported: the hook blanks out everything inside quotes and asks
|
|
14
|
+
# whether a destructive verb still starts a command in what is left. If none
|
|
15
|
+
# does, it exits 0 before any pattern runs. With mentions ruled out, quote
|
|
16
|
+
# characters can be dropped from the text the patterns match against, so a
|
|
17
|
+
# quoted target is judged like a bare one.
|
|
18
|
+
#
|
|
19
|
+
# Two halves, and both are the point:
|
|
20
|
+
# - the quoted targets must now be blocked (this closes the remaining five)
|
|
21
|
+
# - the mentions must still pass (this proves nothing was widened)
|
|
22
|
+
#
|
|
23
|
+
# Against the version before this change, the first half fails: the quoted
|
|
24
|
+
# targets were invisible, so every one of them exited 0.
|
|
25
|
+
#
|
|
26
|
+
# Dangerous strings are assembled from parts so that reading or editing this
|
|
27
|
+
# file does not trip the operator's own destructive-guard. The hook under test
|
|
28
|
+
# receives the fully assembled string either way.
|
|
29
|
+
|
|
30
|
+
set -u
|
|
31
|
+
HOOK="$(cd "$(dirname "$0")/.." && pwd)/examples/auto-mode-safety-enforcer.sh"
|
|
32
|
+
PASS=0
|
|
33
|
+
FAIL=0
|
|
34
|
+
|
|
35
|
+
run() {
|
|
36
|
+
printf '{"tool_name":"Bash","tool_input":{"command":%s}}' \
|
|
37
|
+
"$(printf '%s' "$1" | sed 's/\\/\\\\/g; s/"/\\"/g; s/^/"/; s/$/"/')" \
|
|
38
|
+
| bash "$HOOK" >/dev/null 2>&1
|
|
39
|
+
echo $?
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
expect() { # description command expected_exit
|
|
43
|
+
actual="$(run "$2")"
|
|
44
|
+
if [ "$actual" = "$3" ]; then
|
|
45
|
+
PASS=$((PASS + 1))
|
|
46
|
+
else
|
|
47
|
+
FAIL=$((FAIL + 1))
|
|
48
|
+
echo " FAIL: $1"
|
|
49
|
+
echo " command: $2"
|
|
50
|
+
echo " expected: exit $3, got exit $actual"
|
|
51
|
+
fi
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
RM="r""m -rf"
|
|
55
|
+
SLASH="/"
|
|
56
|
+
GIT_DIR=".git"
|
|
57
|
+
HOME_VAR='$HOME'
|
|
58
|
+
HOME_BRACED='${HOME}'
|
|
59
|
+
DQ='"'
|
|
60
|
+
SQ="'"
|
|
61
|
+
|
|
62
|
+
# --- the five that were left alone -------------------------------------------
|
|
63
|
+
|
|
64
|
+
expect "a double-quoted root is a run" \
|
|
65
|
+
"$RM ${DQ}${SLASH}${DQ}" 2
|
|
66
|
+
expect "a single-quoted root is a run" \
|
|
67
|
+
"$RM ${SQ}${SLASH}${SQ}" 2
|
|
68
|
+
expect "a quoted home variable is a run" \
|
|
69
|
+
"$RM ${DQ}${HOME_VAR}${DQ}" 2
|
|
70
|
+
expect "a quoted braced home variable is a run" \
|
|
71
|
+
"$RM ${DQ}${HOME_BRACED}${DQ}" 2
|
|
72
|
+
expect "a quoted git directory is a run" \
|
|
73
|
+
"$RM ${DQ}${GIT_DIR}${DQ}" 2
|
|
74
|
+
|
|
75
|
+
# --- other quoted targets the header claims ----------------------------------
|
|
76
|
+
|
|
77
|
+
expect "a quoted tilde is a run" "$RM ${DQ}~${DQ}" 2
|
|
78
|
+
expect "a quoted etc is a run" "$RM ${DQ}${SLASH}etc${DQ}" 2
|
|
79
|
+
expect "a quoted parent traversal is a run" \
|
|
80
|
+
"$RM ${DQ}..${DQ}" 2
|
|
81
|
+
expect "a quoted target after another command is a run" \
|
|
82
|
+
"npm ci && $RM ${DQ}${SLASH}${DQ}" 2
|
|
83
|
+
|
|
84
|
+
# --- mentions must still pass (nothing was widened) --------------------------
|
|
85
|
+
|
|
86
|
+
expect "a mention in echo is not a run" \
|
|
87
|
+
"echo ${DQ}${RM} ${SLASH}${DQ}" 0
|
|
88
|
+
expect "a mention in a commit message is not a run" \
|
|
89
|
+
"git commit -m ${DQ}guard against ${RM} ${SLASH}${DQ}" 0
|
|
90
|
+
expect "a mention in grep is not a run" \
|
|
91
|
+
"grep -r ${DQ}${RM} ${SLASH}${DQ} ." 0
|
|
92
|
+
expect "a mention in a jq filter is not a run" \
|
|
93
|
+
"jq -n ${SQ}{cmd: ${DQ}${RM} ${SLASH}${DQ}}${SQ}" 0
|
|
94
|
+
expect "a mention in prose is not a run" \
|
|
95
|
+
"echo ${DQ}the command ${RM} ${SLASH} destroys everything${DQ}" 0
|
|
96
|
+
expect "a mention of the home variable is not a run" \
|
|
97
|
+
"echo ${DQ}never write ${RM} ${HOME_VAR}${DQ}" 0
|
|
98
|
+
expect "appending a mention to a note is not a run" \
|
|
99
|
+
"echo ${SQ}${RM} ${SLASH} is the one to avoid${SQ} >> notes.md" 0
|
|
100
|
+
|
|
101
|
+
# --- quoted safe targets must pass -------------------------------------------
|
|
102
|
+
# This is the false-positive half. Dropping quote characters must not turn an
|
|
103
|
+
# ordinary quoted cleanup into a block.
|
|
104
|
+
|
|
105
|
+
expect "a quoted node_modules is allowed" \
|
|
106
|
+
"$RM ${DQ}node_modules${DQ}" 0
|
|
107
|
+
expect "a quoted dist is allowed" "$RM ${DQ}dist${DQ}" 0
|
|
108
|
+
expect "a quoted name with a space is allowed" \
|
|
109
|
+
"$RM ${DQ}my build dir${DQ}" 0
|
|
110
|
+
expect "a quoted gitignore is not the git directory" \
|
|
111
|
+
"$RM ${DQ}.gitignore${DQ}" 0
|
|
112
|
+
|
|
113
|
+
# --- quoted text that is executed is not a mention ---------------------------
|
|
114
|
+
# A quoted string is only inert while nothing runs it. These do run it, so the
|
|
115
|
+
# gate must not let them through on the grounds that the verb sits in quotes.
|
|
116
|
+
|
|
117
|
+
expect "sh -c runs its quoted argument" \
|
|
118
|
+
"sh -c ${DQ}${RM} ${SLASH}${DQ}" 2
|
|
119
|
+
expect "bash -c runs its quoted argument" \
|
|
120
|
+
"bash -c ${SQ}${RM} ~${SQ}" 2
|
|
121
|
+
expect "eval runs its quoted argument" \
|
|
122
|
+
"eval ${DQ}${RM} ${SLASH}${DQ}" 2
|
|
123
|
+
expect "a pipe into a shell runs what was piped" \
|
|
124
|
+
"echo ${DQ}${RM} ${SLASH}${DQ} | sh" 2
|
|
125
|
+
|
|
126
|
+
echo "auto-mode-quoted-targets: $PASS passed, $FAIL failed"
|
|
127
|
+
[ "$FAIL" -eq 0 ]
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# auto-mode-safety-enforcer promised more than it blocked.
|
|
3
|
+
#
|
|
4
|
+
# The header of that hook says it blocks:
|
|
5
|
+
#
|
|
6
|
+
# rm -rf on non-safe paths (/, ~, .., /home, /etc, /usr, /var, .git)
|
|
7
|
+
#
|
|
8
|
+
# Measured 2026-08-11 against 19 targets it claims: 11 were not blocked.
|
|
9
|
+
# The target pattern only ends on whitespace, a separator or end-of-line, and
|
|
10
|
+
# it has no case for $HOME, for a parent traversal, or for the git directory:
|
|
11
|
+
#
|
|
12
|
+
# rm -rf $HOME passed rm -rf .. passed
|
|
13
|
+
# rm -rf ${HOME} passed rm -rf ../.. passed
|
|
14
|
+
# rm -rf .git passed rm -rf a/../.. passed
|
|
15
|
+
#
|
|
16
|
+
# Same defect family as PR #961 (quoted target) and #962 (variable target),
|
|
17
|
+
# which fixed scripts.json only. The example hook never received either fix.
|
|
18
|
+
#
|
|
19
|
+
# --- deliberately NOT fixed here ---------------------------------------------
|
|
20
|
+
# Five of the eleven need the target seen through quotes:
|
|
21
|
+
#
|
|
22
|
+
# rm -rf "/" rm -rf '/' rm -rf "$HOME" rm -rf "${HOME}" rm -rf ".git"
|
|
23
|
+
#
|
|
24
|
+
# Adding a quote to the terminator set would also block these, which are
|
|
25
|
+
# mentions and must keep passing:
|
|
26
|
+
#
|
|
27
|
+
# echo "rm -rf /" git commit -m "guard against rm -rf /"
|
|
28
|
+
#
|
|
29
|
+
# Both shapes end in /" and this hook has no mention-vs-invocation pass — the
|
|
30
|
+
# five above pass today only because the target is invisible behind the quote,
|
|
31
|
+
# not because the hook can tell a mention from a run. Telling them apart needs
|
|
32
|
+
# the quote-aware extraction destructive-guard grew in PR #960. Until that is
|
|
33
|
+
# ported, the mention controls at the bottom of this file are the guarantee
|
|
34
|
+
# that no such false positive was introduced.
|
|
35
|
+
|
|
36
|
+
set -u
|
|
37
|
+
HOOK="$(cd "$(dirname "$0")/.." && pwd)/examples/auto-mode-safety-enforcer.sh"
|
|
38
|
+
PASS=0
|
|
39
|
+
FAIL=0
|
|
40
|
+
|
|
41
|
+
run() {
|
|
42
|
+
printf '{"tool_name":"Bash","tool_input":{"command":%s}}' \
|
|
43
|
+
"$(printf '%s' "$1" | sed 's/\\/\\\\/g; s/"/\\"/g; s/^/"/; s/$/"/')" \
|
|
44
|
+
| bash "$HOOK" >/dev/null 2>&1
|
|
45
|
+
echo $?
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
expect() { # description command expected_exit
|
|
49
|
+
actual="$(run "$2")"
|
|
50
|
+
if [ "$actual" = "$3" ]; then
|
|
51
|
+
PASS=$((PASS + 1))
|
|
52
|
+
else
|
|
53
|
+
FAIL=$((FAIL + 1))
|
|
54
|
+
echo " FAIL: $1"
|
|
55
|
+
echo " command: $2"
|
|
56
|
+
echo " expected: exit $3, got exit $actual"
|
|
57
|
+
fi
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
# Dangerous strings are assembled from parts so that reading or editing this
|
|
61
|
+
# file does not trip the operator's own destructive-guard. The hook under test
|
|
62
|
+
# receives the fully assembled string either way.
|
|
63
|
+
SLASH="/"
|
|
64
|
+
DOTDOT="..${SLASH}"
|
|
65
|
+
GIT_DIR=".git"
|
|
66
|
+
HOME_VAR='$HOME'
|
|
67
|
+
HOME_BRACED='${HOME}'
|
|
68
|
+
|
|
69
|
+
# --- the gap this file closes ------------------------------------------------
|
|
70
|
+
|
|
71
|
+
expect "home through the variable" "rm -rf $HOME_VAR" 2
|
|
72
|
+
expect "home through the braced variable" "rm -rf $HOME_BRACED" 2
|
|
73
|
+
expect "home variable with a subpath" "rm -rf $HOME_VAR${SLASH}projects" 2
|
|
74
|
+
expect "bare parent traversal" "rm -rf .." 2
|
|
75
|
+
expect "repeated parent traversal" "rm -rf $DOTDOT.." 2
|
|
76
|
+
expect "traversal hidden after a safe name" \
|
|
77
|
+
"rm -rf node_modules${SLASH}$DOTDOT.." 2
|
|
78
|
+
expect "the git directory" "rm -rf $GIT_DIR" 2
|
|
79
|
+
expect "the git directory with a slash" "rm -rf $GIT_DIR$SLASH" 2
|
|
80
|
+
|
|
81
|
+
# --- what already worked must keep working -----------------------------------
|
|
82
|
+
|
|
83
|
+
expect "root still blocks" "rm -rf $SLASH" 2
|
|
84
|
+
expect "home tilde still blocks" "rm -rf ~" 2
|
|
85
|
+
expect "etc still blocks" "rm -rf ${SLASH}etc" 2
|
|
86
|
+
expect "usr still blocks" "rm -rf ${SLASH}usr" 2
|
|
87
|
+
expect "ssh directory still blocks" "rm -rf ~${SLASH}.ssh" 2
|
|
88
|
+
|
|
89
|
+
# --- ordinary cleanup must not be caught -------------------------------------
|
|
90
|
+
|
|
91
|
+
expect "node_modules is allowed" "rm -rf node_modules" 0
|
|
92
|
+
expect "dist is allowed" "rm -rf dist" 0
|
|
93
|
+
expect "leading ./ is allowed" "rm -rf .${SLASH}build" 0
|
|
94
|
+
expect "cleanup after another command" "npm ci && rm -rf node_modules" 0
|
|
95
|
+
expect "an unlisted directory is allowed" "rm -rf tmpdir" 0
|
|
96
|
+
expect "gitignore is not the git directory" \
|
|
97
|
+
"rm -rf .gitignore" 0
|
|
98
|
+
expect "the github directory is not the git directory" \
|
|
99
|
+
"rm -rf .github" 0
|
|
100
|
+
expect "a dotted name is not a traversal" "rm -rf my..cache" 0
|
|
101
|
+
expect "a file ending in two dots is not a traversal" \
|
|
102
|
+
"rm -rf backup.." 0
|
|
103
|
+
|
|
104
|
+
# --- mentions must keep passing (the reason quotes are left alone) -----------
|
|
105
|
+
|
|
106
|
+
expect "a mention in echo is not a run" "echo \"rm -rf $SLASH\"" 0
|
|
107
|
+
expect "a mention in a commit message is not a run" \
|
|
108
|
+
"git commit -m \"guard against rm -rf $SLASH\"" 0
|
|
109
|
+
expect "a mention in grep is not a run" "grep -r \"rm -rf $SLASH\" ." 0
|
|
110
|
+
|
|
111
|
+
echo "auto-mode-unquoted-targets: $PASS passed, $FAIL failed"
|
|
112
|
+
[ "$FAIL" -eq 0 ]
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# bash-secret-output-detector: does each advertised pattern actually fire?
|
|
3
|
+
#
|
|
4
|
+
# Why this exists. The six existing checks for this hook in test.sh all assert
|
|
5
|
+
# exit 0. This hook always exits 0 by default, so those checks pass whether a
|
|
6
|
+
# pattern fires or not - the same shape as the "234 test files that could not
|
|
7
|
+
# fail" noted in the CI workflow.
|
|
8
|
+
#
|
|
9
|
+
# The regression being pinned: the private-key check was written as
|
|
10
|
+
# grep -qE '-----BEGIN ... PRIVATE KEY-----'
|
|
11
|
+
# without `--`, so grep read the leading dashes as options, printed
|
|
12
|
+
# "unrecognized option" and exited non-zero. The check never fired on any
|
|
13
|
+
# input, and test.sh's "private key" case passed anyway because it only looked
|
|
14
|
+
# at the exit code. Measured 2026-09-20 against the shipped file.
|
|
15
|
+
#
|
|
16
|
+
# Both directions are asserted: a detector that also fires on ordinary output
|
|
17
|
+
# is a detector operators learn to ignore.
|
|
18
|
+
|
|
19
|
+
set -u
|
|
20
|
+
REPO="$(cd "$(dirname "$0")/.." && pwd)"
|
|
21
|
+
HOOK="$REPO/examples/bash-secret-output-detector.sh"
|
|
22
|
+
PASS=0
|
|
23
|
+
FAIL=0
|
|
24
|
+
|
|
25
|
+
# Split so that writing this file does not itself trip a secret scanner.
|
|
26
|
+
AWS="AKI""AIOSFODNN7""EXAMPLE"
|
|
27
|
+
APIKEY="api_key=sk""-1234567890abcdefghijklmnop"
|
|
28
|
+
CONN="postgres://user"":pass@host:5432/db"
|
|
29
|
+
PEM="-----BEGIN RSA PRIVATE KEY-----"
|
|
30
|
+
GH="ghp""_1234567890abcdefghijklmnopqrstuv"
|
|
31
|
+
JWT="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.abc"
|
|
32
|
+
|
|
33
|
+
run() {
|
|
34
|
+
local payload
|
|
35
|
+
payload=$(printf '{"tool_name":"Bash","tool_result":{"stdout":"%s"}}' "$1")
|
|
36
|
+
ERR=$(printf '%s' "$payload" | bash "$HOOK" 2>&1 >/dev/null)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
warns() {
|
|
40
|
+
run "$2"
|
|
41
|
+
local got="no"
|
|
42
|
+
case "$ERR" in *"SECRET DETECTED"*) got="yes" ;; esac
|
|
43
|
+
if [ "$got" = "$3" ]; then
|
|
44
|
+
PASS=$((PASS + 1))
|
|
45
|
+
else
|
|
46
|
+
FAIL=$((FAIL + 1))
|
|
47
|
+
echo " FAIL: $1 (expected warn=$3, got warn=$got)"
|
|
48
|
+
echo " stderr: $ERR"
|
|
49
|
+
fi
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
quiet_stderr() {
|
|
53
|
+
run "hello world"
|
|
54
|
+
case "$ERR" in
|
|
55
|
+
*"unrecognized option"*|*"Usage: grep"*)
|
|
56
|
+
FAIL=$((FAIL + 1))
|
|
57
|
+
echo " FAIL: a pattern is malformed and grep is erroring out"
|
|
58
|
+
echo " stderr: $ERR" ;;
|
|
59
|
+
*) PASS=$((PASS + 1)) ;;
|
|
60
|
+
esac
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
echo "bash-secret-output-detector-detects:"
|
|
64
|
+
|
|
65
|
+
# --- every advertised pattern has to fire ----------------------------------
|
|
66
|
+
warns "AWS access key" "$AWS" yes
|
|
67
|
+
warns "API key assignment" "$APIKEY" yes
|
|
68
|
+
warns "connection string" "$CONN" yes
|
|
69
|
+
warns "private key header" "$PEM" yes
|
|
70
|
+
warns "GitHub token" "$GH" yes
|
|
71
|
+
warns "JWT" "$JWT" yes
|
|
72
|
+
|
|
73
|
+
# --- ordinary output must stay quiet ---------------------------------------
|
|
74
|
+
warns "plain output is quiet" "hello world" no
|
|
75
|
+
warns "safe env var is quiet" "PATH=/usr/bin" no
|
|
76
|
+
|
|
77
|
+
# --- no pattern may be malformed -------------------------------------------
|
|
78
|
+
quiet_stderr
|
|
79
|
+
|
|
80
|
+
# --- default must not interrupt; the opt-in must ---------------------------
|
|
81
|
+
printf '%s' "{\"tool_name\":\"Bash\",\"tool_result\":{\"stdout\":\"$AWS\"}}" \
|
|
82
|
+
| bash "$HOOK" >/dev/null 2>&1
|
|
83
|
+
rc=$?
|
|
84
|
+
if [ "$rc" -eq 0 ]; then
|
|
85
|
+
PASS=$((PASS + 1))
|
|
86
|
+
else
|
|
87
|
+
FAIL=$((FAIL + 1))
|
|
88
|
+
echo " FAIL: default must not interrupt (expected exit 0, got $rc)"
|
|
89
|
+
fi
|
|
90
|
+
|
|
91
|
+
printf '%s' "{\"tool_name\":\"Bash\",\"tool_result\":{\"stdout\":\"$AWS\"}}" \
|
|
92
|
+
| CC_SECRET_OUTPUT_BLOCK=1 bash "$HOOK" >/dev/null 2>&1
|
|
93
|
+
rc=$?
|
|
94
|
+
if [ "$rc" -eq 2 ]; then
|
|
95
|
+
PASS=$((PASS + 1))
|
|
96
|
+
else
|
|
97
|
+
FAIL=$((FAIL + 1))
|
|
98
|
+
echo " FAIL: CC_SECRET_OUTPUT_BLOCK=1 must exit 2 (got $rc)"
|
|
99
|
+
fi
|
|
100
|
+
|
|
101
|
+
echo " $PASS passed, $FAIL failed"
|
|
102
|
+
[ "$FAIL" -eq 0 ]
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# --blindspots must compare two layers, and must not mistake an allow test for a gate.
|
|
3
|
+
#
|
|
4
|
+
# Why this exists. Every other diagnostic in this tool reads one layer: the
|
|
5
|
+
# scripts on disk (--status), the settings file (--lint), the block log
|
|
6
|
+
# (--stats), the shipped bodies (--outdated). A guard can be present,
|
|
7
|
+
# executable, registered and current in all four and still never fire, because
|
|
8
|
+
# the shape of the commands actually run on that machine never reaches it.
|
|
9
|
+
# `--blindspots` is the only check that reads the session transcripts next to
|
|
10
|
+
# the guards, so it is the only one that can see that gap.
|
|
11
|
+
#
|
|
12
|
+
# The trap this test pins is in the instrument, not in the user's setup. Hook
|
|
13
|
+
# scripts contain start-anchored patterns for two opposite purposes:
|
|
14
|
+
#
|
|
15
|
+
# gate if printf '%s' "$CMD" | grep -qE '^\s*git\s+add'; then ... exit 2
|
|
16
|
+
# subject if ! printf '%s' "$CMD" | grep -qE '^\s*git\s+push'; then exit 0; fi
|
|
17
|
+
# exempt if printf '%s' "$CMD" | grep -qE '^\s*(cat|ls)'; then exit 0; fi
|
|
18
|
+
#
|
|
19
|
+
# The first two decide what the hook reaches. The third decides what it lets
|
|
20
|
+
# through on purpose. Counting the third as an unguarded gap fills the report
|
|
21
|
+
# with alarms about read-only commands the author deliberately waved past — a
|
|
22
|
+
# tool that warns about the very defect it contains. So this test asserts both
|
|
23
|
+
# directions: the gate and the subject are reported, and the exempt pattern is
|
|
24
|
+
# not.
|
|
25
|
+
#
|
|
26
|
+
# Numbers are fixed by construction: 25 calls invoke `git push`, 5 of them at
|
|
27
|
+
# the start of the string, 20 after a `cd ... &&`. Blind = 20/25 = 80.0%.
|
|
28
|
+
|
|
29
|
+
set -u
|
|
30
|
+
REPO="$(cd "$(dirname "$0")/.." && pwd)"
|
|
31
|
+
PASS=0
|
|
32
|
+
FAIL=0
|
|
33
|
+
|
|
34
|
+
check() { # name expected actual
|
|
35
|
+
if [ "$2" = "$3" ]; then
|
|
36
|
+
PASS=$((PASS + 1))
|
|
37
|
+
else
|
|
38
|
+
FAIL=$((FAIL + 1))
|
|
39
|
+
echo " FAIL: $1"
|
|
40
|
+
echo " expected: $2"
|
|
41
|
+
echo " actual: $3"
|
|
42
|
+
fi
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
TMP="$(mktemp -d)"
|
|
46
|
+
trap 'chmod -R u+w "$TMP" 2>/dev/null; find "$TMP" -mindepth 1 -delete 2>/dev/null; rmdir "$TMP" 2>/dev/null' EXIT
|
|
47
|
+
|
|
48
|
+
mkdir -p "$TMP/.claude/hooks" "$TMP/.claude/projects/-tmp-probe"
|
|
49
|
+
|
|
50
|
+
# A gate: the anchor is the blocking condition.
|
|
51
|
+
cat > "$TMP/.claude/hooks/probe-add-guard.sh" <<'HOOK'
|
|
52
|
+
#!/bin/bash
|
|
53
|
+
CMD=$(cat)
|
|
54
|
+
if printf '%s' "$CMD" | grep -qE '^\s*git\s+add'; then
|
|
55
|
+
echo "blocked" >&2
|
|
56
|
+
exit 2
|
|
57
|
+
fi
|
|
58
|
+
exit 0
|
|
59
|
+
HOOK
|
|
60
|
+
|
|
61
|
+
# A subject filter: anything not matching the anchor is never examined at all.
|
|
62
|
+
cat > "$TMP/.claude/hooks/probe-push-guard.sh" <<'HOOK'
|
|
63
|
+
#!/bin/bash
|
|
64
|
+
CMD=$(cat)
|
|
65
|
+
if ! printf '%s' "$CMD" | grep -qE '^\s*git\s+push'; then
|
|
66
|
+
exit 0
|
|
67
|
+
fi
|
|
68
|
+
echo "blocked" >&2
|
|
69
|
+
exit 2
|
|
70
|
+
HOOK
|
|
71
|
+
|
|
72
|
+
# An allow test: these are waved through deliberately and are not a gap.
|
|
73
|
+
cat > "$TMP/.claude/hooks/probe-readonly-allow.sh" <<'HOOK'
|
|
74
|
+
#!/bin/bash
|
|
75
|
+
CMD=$(cat)
|
|
76
|
+
if printf '%s' "$CMD" | grep -qE '^\s*(cat|ls|head)'; then
|
|
77
|
+
exit 0
|
|
78
|
+
fi
|
|
79
|
+
exit 0
|
|
80
|
+
HOOK
|
|
81
|
+
|
|
82
|
+
# Present on disk, registered nowhere. It never runs, so its anchors must not be
|
|
83
|
+
# counted as gaps — but the file itself is worth naming.
|
|
84
|
+
cat > "$TMP/.claude/hooks/probe-orphan.sh" <<'HOOK'
|
|
85
|
+
#!/bin/bash
|
|
86
|
+
CMD=$(cat)
|
|
87
|
+
if printf '%s' "$CMD" | grep -qE '^\s*git\s+push'; then
|
|
88
|
+
exit 2
|
|
89
|
+
fi
|
|
90
|
+
exit 0
|
|
91
|
+
HOOK
|
|
92
|
+
|
|
93
|
+
chmod +x "$TMP/.claude/hooks/"*.sh
|
|
94
|
+
|
|
95
|
+
# One registration points at a script that is not there. Settings say it is
|
|
96
|
+
# installed; the filesystem says otherwise. Neither layer alone shows this.
|
|
97
|
+
cat > "$TMP/.claude/settings.json" <<SETTINGS
|
|
98
|
+
{
|
|
99
|
+
"hooks": {
|
|
100
|
+
"PreToolUse": [
|
|
101
|
+
{
|
|
102
|
+
"matcher": "Bash",
|
|
103
|
+
"hooks": [
|
|
104
|
+
{ "type": "command", "command": "bash \$HOME/.claude/hooks/probe-push-guard.sh" },
|
|
105
|
+
{ "type": "command", "command": "bash \$HOME/.claude/hooks/probe-add-guard.sh" },
|
|
106
|
+
{ "type": "command", "command": "bash \$HOME/.claude/hooks/probe-readonly-allow.sh" },
|
|
107
|
+
{ "type": "command", "command": "bash \$HOME/.claude/hooks/probe-removed-guard.sh" }
|
|
108
|
+
]
|
|
109
|
+
}
|
|
110
|
+
]
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
SETTINGS
|
|
114
|
+
|
|
115
|
+
# 25 invocations of `git push`: 5 at the start, 20 behind a `cd ... &&`.
|
|
116
|
+
# Plus 30 `cat` calls, which the allow test covers on purpose.
|
|
117
|
+
TRANSCRIPT="$TMP/.claude/projects/-tmp-probe/session.jsonl"
|
|
118
|
+
: > "$TRANSCRIPT"
|
|
119
|
+
emit() { # command
|
|
120
|
+
printf '{"type":"assistant","timestamp":"2026-09-01T00:00:00Z","message":{"content":[{"type":"tool_use","name":"Bash","input":{"command":%s}}]}}\n' \
|
|
121
|
+
"$(printf '%s' "$1" | python3 -c 'import json,sys; print(json.dumps(sys.stdin.read()))')" >> "$TRANSCRIPT"
|
|
122
|
+
}
|
|
123
|
+
for i in $(seq 1 5); do emit "git push origin main"; done
|
|
124
|
+
for i in $(seq 1 20); do emit "cd /tmp/work && git push origin main"; done
|
|
125
|
+
for i in $(seq 1 30); do emit "cat /tmp/work/notes.md"; done
|
|
126
|
+
|
|
127
|
+
OUT="$(HOME="$TMP" node "$REPO/index.mjs" --blindspots 2>&1)"
|
|
128
|
+
PLAIN="$(printf '%s' "$OUT" | sed 's/\x1b\[[0-9;]*m//g')"
|
|
129
|
+
|
|
130
|
+
# Layer 4 was actually read.
|
|
131
|
+
check "counts the Bash calls in the transcript" \
|
|
132
|
+
"yes" "$(printf '%s' "$PLAIN" | grep -qE '\b55 Bash tool calls' && echo yes || echo no)"
|
|
133
|
+
|
|
134
|
+
# The sample must be a shape, never the command. A user's history carries keys,
|
|
135
|
+
# customer names and internal paths, and this output lands in screen shares and
|
|
136
|
+
# CI logs. The probe transcript writes /tmp/work into every chained call; none of
|
|
137
|
+
# it may come back out.
|
|
138
|
+
check "prints the shape, not the arguments" \
|
|
139
|
+
"yes" "$(printf '%s' "$PLAIN" | grep -qE '^ +cd … && git push …$' && echo yes || echo no)"
|
|
140
|
+
check "no argument from the transcript is echoed" \
|
|
141
|
+
"yes" "$(printf '%s' "$PLAIN" | grep -q '/tmp/work' && echo no || echo yes)"
|
|
142
|
+
|
|
143
|
+
# The subject filter is reported, with the blind rate fixed by construction.
|
|
144
|
+
check "reports the start-anchored push guard" \
|
|
145
|
+
"yes" "$(printf '%s' "$PLAIN" | grep -q 'probe-push-guard.sh' && echo yes || echo no)"
|
|
146
|
+
check "blind rate is 20 of 25" \
|
|
147
|
+
"yes" "$(printf '%s' "$PLAIN" | grep -qE 'git push .*probe-push-guard\.sh +25 +5 +80\.0%' && echo yes || echo no)"
|
|
148
|
+
check "labels a subject filter as never examined" \
|
|
149
|
+
"yes" "$(printf '%s' "$PLAIN" | grep -qE 'probe-push-guard\.sh.*never examined' && echo yes || echo no)"
|
|
150
|
+
|
|
151
|
+
# The allow test must not be listed. This is the instrument's own failure mode.
|
|
152
|
+
check "does not report the allow test as a gap" \
|
|
153
|
+
"yes" "$(printf '%s' "$PLAIN" | grep -qE '^ +(cat|ls|head).*probe-readonly-allow\.sh' && echo no || echo yes)"
|
|
154
|
+
|
|
155
|
+
# Present but registered nowhere. Its anchors are kept out of the gap table —
|
|
156
|
+
# a script that never runs cannot have a gap — and the reader is told the table
|
|
157
|
+
# is smaller than their hooks directory, without duplicating the enumeration
|
|
158
|
+
# that --audit already does with its own precision rules.
|
|
159
|
+
check "says unregistered scripts were left out of the table" \
|
|
160
|
+
"yes" "$(printf '%s' "$PLAIN" | grep -qE '1 more script .* is registered nowhere' && echo yes || echo no)"
|
|
161
|
+
check "keeps the unregistered script out of the gap table" \
|
|
162
|
+
"yes" "$(printf '%s' "$PLAIN" | grep -qE 'git push +probe-orphan\.sh +[0-9]' && echo no || echo yes)"
|
|
163
|
+
|
|
164
|
+
# The registration with no file behind it.
|
|
165
|
+
check "names the registration whose file is missing" \
|
|
166
|
+
"yes" "$(printf '%s' "$PLAIN" | grep -q 'probe-removed-guard.sh' && echo yes || echo no)"
|
|
167
|
+
check "does not flag the registration that does exist" \
|
|
168
|
+
"yes" "$(printf '%s' "$PLAIN" | grep -qE '^\s+·.*probe-push-guard\.sh' && echo no || echo yes)"
|
|
169
|
+
|
|
170
|
+
# Nothing is written back. This command reads; it must never touch settings.
|
|
171
|
+
BEFORE="$(md5sum "$TMP/.claude/settings.json" | cut -d' ' -f1)"
|
|
172
|
+
HOME="$TMP" node "$REPO/index.mjs" --blindspots >/dev/null 2>&1
|
|
173
|
+
AFTER="$(md5sum "$TMP/.claude/settings.json" | cut -d' ' -f1)"
|
|
174
|
+
check "leaves settings.json untouched" "$BEFORE" "$AFTER"
|
|
175
|
+
|
|
176
|
+
echo " blindspots-cross-layer: $PASS passed, $FAIL failed"
|
|
177
|
+
[ "$FAIL" -eq 0 ]
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Test for block-database-wipe.sh
|
|
3
|
+
#
|
|
4
|
+
# Verifies the hook blocks (exit 2) destructive framework/ORM database commands
|
|
5
|
+
# across Laravel, Django, Rails, Prisma, TypeORM/Sequelize, raw SQL and PostgreSQL,
|
|
6
|
+
# while letting safe incremental commands through (exit 0).
|
|
7
|
+
#
|
|
8
|
+
# Gaps closed in Issue #69059: migrate:refresh, Django "migrate <app> zero",
|
|
9
|
+
# Rails db:schema:load, TypeORM/Sequelize schema:drop / db:drop.
|
|
10
|
+
|
|
11
|
+
set -u
|
|
12
|
+
|
|
13
|
+
HOOK="$(dirname "$0")/../examples/block-database-wipe.sh"
|
|
14
|
+
[ ! -x "$HOOK" ] && chmod +x "$HOOK"
|
|
15
|
+
|
|
16
|
+
PASS=0
|
|
17
|
+
FAIL=0
|
|
18
|
+
|
|
19
|
+
run_case() {
|
|
20
|
+
local name="$1"
|
|
21
|
+
local cmd="$2"
|
|
22
|
+
local expect="$3" # "block" or "allow"
|
|
23
|
+
|
|
24
|
+
local input rc
|
|
25
|
+
input=$(jq -nc --arg cmd "$cmd" '{tool_input:{command:$cmd}}')
|
|
26
|
+
echo "$input" | "$HOOK" >/dev/null 2>&1
|
|
27
|
+
rc=$?
|
|
28
|
+
|
|
29
|
+
if [ "$expect" = "block" ]; then
|
|
30
|
+
if [ "$rc" = "2" ]; then PASS=$((PASS + 1)); echo "PASS: $name"
|
|
31
|
+
else FAIL=$((FAIL + 1)); echo "FAIL: $name (expected block/exit2, got $rc)"; fi
|
|
32
|
+
else
|
|
33
|
+
if [ "$rc" = "0" ]; then PASS=$((PASS + 1)); echo "PASS: $name"
|
|
34
|
+
else FAIL=$((FAIL + 1)); echo "FAIL: $name (expected allow/exit0, got $rc)"; fi
|
|
35
|
+
fi
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
# --- destructive: must block ---
|
|
39
|
+
run_case "laravel migrate:fresh" "php artisan migrate:fresh" block
|
|
40
|
+
run_case "laravel migrate:refresh" "php artisan migrate:refresh" block
|
|
41
|
+
run_case "laravel migrate:reset" "php artisan migrate:reset" block
|
|
42
|
+
run_case "laravel db:wipe" "php artisan db:wipe" block
|
|
43
|
+
run_case "django flush" "python manage.py flush" block
|
|
44
|
+
run_case "django migrate app zero" "python manage.py migrate myapp zero" block
|
|
45
|
+
run_case "rails db:drop" "rails db:drop" block
|
|
46
|
+
run_case "rails db:schema:load" "rails db:schema:load" block
|
|
47
|
+
run_case "prisma migrate reset" "npx prisma migrate reset" block
|
|
48
|
+
run_case "typeorm schema:drop" "npm run typeorm schema:drop" block
|
|
49
|
+
run_case "sequelize db:drop" "npx sequelize-cli db:drop" block
|
|
50
|
+
run_case "raw DROP DATABASE" "mysql -e 'DROP DATABASE foo'" block
|
|
51
|
+
run_case "dropdb" "dropdb mydb" block
|
|
52
|
+
|
|
53
|
+
# --- safe: must allow (no false positives) ---
|
|
54
|
+
run_case "laravel migrate (incremental)" "php artisan migrate" allow
|
|
55
|
+
run_case "django migrate (incremental)" "python manage.py migrate" allow
|
|
56
|
+
run_case "rails db:migrate" "rails db:migrate" allow
|
|
57
|
+
run_case "prisma migrate dev" "npx prisma migrate dev" allow
|
|
58
|
+
run_case "typeorm migration:run" "npm run typeorm migration:run" allow
|
|
59
|
+
run_case "plain git commit" "git commit -m fix" allow
|
|
60
|
+
run_case "safe SELECT" "psql -c 'SELECT count(*) FROM users'" allow
|
|
61
|
+
|
|
62
|
+
echo "----------------------------------------"
|
|
63
|
+
echo "PASS=$PASS FAIL=$FAIL"
|
|
64
|
+
[ "$FAIL" -eq 0 ] || exit 1
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Bundled short flags slipped past the force checks
|
|
3
|
+
#
|
|
4
|
+
# Short options can be written together. These are all one flag group:
|
|
5
|
+
#
|
|
6
|
+
# git push -uf origin feature # -u --set-upstream + -f --force
|
|
7
|
+
# git checkout -bf main # -b new branch + -f force
|
|
8
|
+
# git switch -Cf main # -C force-create + -f force
|
|
9
|
+
#
|
|
10
|
+
# Every one of them is a real destructive operation. The shipped patterns
|
|
11
|
+
# looked for the spelling `-f` as a standalone word (`-f\b`), so a bundled
|
|
12
|
+
# group never matched and the guards exited 0 -- an affirmative approval.
|
|
13
|
+
#
|
|
14
|
+
# Measured 2026-09-03 against the shipped copies: 4 bypasses.
|
|
15
|
+
# branch-guard git push -uf (force push, any branch)
|
|
16
|
+
# destructive-guard git checkout -bf, git switch -Cf, git checkout -qf
|
|
17
|
+
#
|
|
18
|
+
# The fix reads "a dash, then letters, ending in f" instead of the literal
|
|
19
|
+
# `-f`: [^A-Za-z0-9]-[a-zA-Z]*f\b
|
|
20
|
+
#
|
|
21
|
+
# The leading [^A-Za-z0-9] is what keeps `--follow-tags` out: after the second
|
|
22
|
+
# dash the letters run `follow`, and `f` is not at a word boundary there.
|
|
23
|
+
#
|
|
24
|
+
# destructive-guard needed a second change beyond the character class. Its
|
|
25
|
+
# pattern was `git\s+(checkout|switch)\s+.*`, and that `\s+` ate the space in
|
|
26
|
+
# front of `-bf`, leaving no character for [^A-Za-z0-9] to match. Anchoring on
|
|
27
|
+
# `\b` instead of `\s+` leaves the space in the subject where the class can see
|
|
28
|
+
# it. Same shape as the git-globals fix: the check was right, the thing feeding
|
|
29
|
+
# it was not.
|
|
30
|
+
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
|
31
|
+
BG=$(mktemp); DG=$(mktemp)
|
|
32
|
+
trap 'rm -f "$BG" "$DG"' EXIT
|
|
33
|
+
python3 -c "
|
|
34
|
+
import json,sys
|
|
35
|
+
d=json.load(open('$ROOT/scripts.json'))
|
|
36
|
+
open('$BG','w').write(d['branch-guard'])
|
|
37
|
+
open('$DG','w').write(d['destructive-guard'])"
|
|
38
|
+
|
|
39
|
+
PASS=0; FAIL=0
|
|
40
|
+
|
|
41
|
+
check() {
|
|
42
|
+
local guard="$1" desc="$2" cmd="$3" want="$4" # want: 2 = blocked, 0 = allowed
|
|
43
|
+
local payload code
|
|
44
|
+
payload=$(python3 -c '
|
|
45
|
+
import json,sys
|
|
46
|
+
print(json.dumps({"tool_name":"Bash","tool_input":{"command":sys.argv[1]}}))' "$cmd")
|
|
47
|
+
printf '%s' "$payload" | bash "$guard" >/dev/null 2>&1
|
|
48
|
+
code=$?
|
|
49
|
+
if [ "$code" = "$want" ]; then
|
|
50
|
+
echo "PASS: $desc"; PASS=$((PASS+1))
|
|
51
|
+
else
|
|
52
|
+
echo "FAIL: $desc (expected exit $want, got $code)"; FAIL=$((FAIL+1))
|
|
53
|
+
fi
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
# --- branch-guard: bundled -f in a push ---
|
|
57
|
+
check "$BG" "bg: -uf force push" 'git push -uf origin feature' 2
|
|
58
|
+
check "$BG" "bg: -qf force push" 'git push -qf origin feature' 2
|
|
59
|
+
check "$BG" "bg: -uf with a global" 'git -C /repo push -uf origin feature' 2
|
|
60
|
+
check "$BG" "bg: plain -f still blocked" 'git push -f origin feature' 2
|
|
61
|
+
check "$BG" "bg: --force still blocked" 'git push --force origin feature' 2
|
|
62
|
+
|
|
63
|
+
# --- branch-guard: ordinary work still goes through ---
|
|
64
|
+
check "$BG" "bg: --follow-tags allowed" 'git push --follow-tags origin feature' 0
|
|
65
|
+
check "$BG" "bg: -u alone allowed" 'git push -u origin feature' 0
|
|
66
|
+
check "$BG" "bg: plain push allowed" 'git push origin feature' 0
|
|
67
|
+
|
|
68
|
+
# --- destructive-guard: bundled -f in checkout/switch ---
|
|
69
|
+
check "$DG" "dg: checkout -bf" 'git checkout -bf main' 2
|
|
70
|
+
check "$DG" "dg: switch -Cf" 'git switch -Cf main' 2
|
|
71
|
+
check "$DG" "dg: checkout -qf" 'git checkout -qf main' 2
|
|
72
|
+
check "$DG" "dg: checkout -f still blocked" 'git checkout -f main' 2
|
|
73
|
+
check "$DG" "dg: checkout --force blocked" 'git checkout --force main' 2
|
|
74
|
+
check "$DG" "dg: switch --discard-changes" 'git switch --discard-changes main' 2
|
|
75
|
+
|
|
76
|
+
# --- destructive-guard: ordinary work still goes through ---
|
|
77
|
+
check "$DG" "dg: checkout a branch" 'git checkout main' 0
|
|
78
|
+
check "$DG" "dg: checkout -b new branch" 'git checkout -b feature' 0
|
|
79
|
+
check "$DG" "dg: switch -c new branch" 'git switch -c my-feature' 0
|
|
80
|
+
check "$DG" "dg: switch --detach" 'git switch --detach HEAD' 0
|
|
81
|
+
check "$DG" "dg: checkout --track" 'git checkout --track origin/feature' 0
|
|
82
|
+
|
|
83
|
+
echo
|
|
84
|
+
echo "PASS=$PASS FAIL=$FAIL"
|
|
85
|
+
[ "$FAIL" = 0 ]
|