cc-safe-setup 29.8.0 → 30.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +72 -19
- package/.claude-plugin/plugin.json +1 -1
- package/CONTRIBUTING.md +7 -2
- package/COOKBOOK.md +50 -46
- package/LICENSE +21 -0
- package/MIGRATION.md +8 -8
- package/README.md +419 -512
- package/SAFETY_CHECKLIST.md +15 -7
- package/SERVICES.md +194 -0
- package/SETTINGS_REFERENCE.md +236 -17
- package/SKILL.md +5 -5
- package/TROUBLESHOOTING.md +35 -14
- package/action.yml +12 -4
- package/audit/README.md +84 -0
- package/audit/audit-checklist.md +152 -0
- package/audit/boundary-selftest.sh +85 -0
- package/audit/boundary.sh +123 -0
- package/audit/count-hooks.py +42 -0
- package/audit/find-dead-hooks.sh +82 -0
- package/audit/find-unfirable-rules.sh +142 -0
- package/audit/fire.sh +97 -0
- package/audit/selftest.sh +42 -0
- package/audit/unfirable-selftest.sh +81 -0
- package/audit-web/index.html +9 -9
- package/examples/README.md +54 -17
- package/examples/account-billing-log.sh +98 -0
- package/examples/account-routing-preflight.sh +123 -0
- package/examples/agent-sdk-credit-pool-monitor.sh +145 -0
- package/examples/agent-view-quota-decrement.sh +32 -0
- package/examples/agent-view-quota-warn.sh +94 -0
- package/examples/agents-md-edit-drift-warner.sh +223 -0
- package/examples/agents-md-loader.sh +160 -0
- package/examples/agents-md-sync-checker.sh +102 -0
- package/examples/ai-slop-punctuation-arrest.sh +210 -0
- package/examples/allowlist.sh +70 -10
- package/examples/always-allow-pattern-suggester.sh +125 -0
- package/examples/ansible-vault-guard.sh +2 -1
- package/examples/anthropic-base-url-guard.sh +76 -0
- package/examples/api-busyloop-guard.sh +123 -0
- package/examples/api-endpoint-guard.sh +12 -0
- package/examples/api-key-in-url-guard.sh +17 -1
- package/examples/api-rate-limit-guard.sh +36 -1
- package/examples/api-rate-limit-tracker.sh +12 -0
- package/examples/articulated-scope-capture.sh +101 -0
- package/examples/askuserquestion-autonomy-gate.sh +102 -0
- package/examples/attachment-traversal-guard.sh +118 -0
- package/examples/aup-block-pattern-logger.sh +161 -0
- package/examples/aup-false-positive-helper.sh +124 -0
- package/examples/aup-large-tool-output-warner.sh +282 -0
- package/examples/aup-retry-loop-guard.sh +229 -0
- package/examples/auth-expiry-reminder.sh +157 -0
- package/examples/auth-macos-sleep-detector.sh +185 -0
- package/examples/auth-path-detector.sh +171 -0
- package/examples/auth-status-checker.sh +157 -0
- package/examples/authorized-reconfirmation-detector.sh +195 -0
- package/examples/auto-approve-build.sh +39 -0
- package/examples/auto-approve-cargo.sh +31 -1
- package/examples/auto-approve-docker.sh +35 -0
- package/examples/auto-approve-git-read.sh +37 -14
- package/examples/auto-approve-go.sh +30 -1
- package/examples/auto-approve-gradle.sh +29 -1
- package/examples/auto-approve-make.sh +29 -1
- package/examples/auto-approve-maven.sh +29 -1
- package/examples/auto-approve-python.sh +41 -1
- package/examples/auto-approve-readonly-tools.sh +1 -0
- package/examples/auto-approve-readonly.sh +110 -33
- package/examples/auto-approve-ssh.sh +30 -1
- package/examples/auto-approve-test.sh +44 -0
- package/examples/auto-checkpoint.sh +1 -1
- package/examples/auto-compact-prep.sh +0 -0
- package/examples/auto-git-checkpoint.sh +0 -0
- package/examples/auto-mode-safe-commands.sh +53 -1
- package/examples/auto-mode-safety-enforcer.sh +151 -4
- package/examples/auto-push-session-branch.sh +22 -0
- package/examples/aws-production-guard.sh +13 -1
- package/examples/aws-region-guard.sh +1 -1
- package/examples/background-cost-launch-guard.sh +82 -0
- package/examples/background-task-guard.sh +12 -0
- package/examples/backup-before-refactor.sh +0 -0
- package/examples/banned-command-guard.sh +12 -0
- package/examples/bash-allowlist-secondary-check.sh +157 -0
- package/examples/bash-domain-allowlist.sh +12 -0
- package/examples/bash-fanout-bounded-rewriter.sh +191 -0
- package/examples/bash-heuristic-approver.sh +112 -10
- package/examples/bash-project-fence.sh +194 -0
- package/examples/bash-safety-auto-deny.sh +12 -0
- package/examples/bash-secret-output-detector.sh +44 -3
- package/examples/bash-trace-guard.sh +12 -0
- package/examples/bashrc-safety-check.sh +0 -0
- package/examples/bg-permission-prompt-warner.sh +182 -0
- package/examples/bg-task-cooldown-guard.sh +12 -0
- package/examples/binary-read-detector.sh +135 -0
- package/examples/binary-upload-guard.sh +12 -0
- package/examples/block-database-wipe.sh +35 -10
- package/examples/branch-name-check.sh +8 -3
- package/examples/branch-naming-convention.sh +0 -0
- package/examples/broad-find-guard.sh +12 -0
- package/examples/broad-prefix-session-trap-warner.sh +106 -0
- package/examples/bulk-file-delete-guard.sh +45 -0
- package/examples/bypass-mode-effective-verifier.sh +203 -0
- package/examples/cache-creation-drift-detector.sh +120 -0
- package/examples/cache-residue-detector.sh +195 -0
- package/examples/cache-tier-logger.sh +70 -0
- package/examples/cache-ttl-eviction-detector.sh +149 -0
- package/examples/cargo-publish-guard.sh +14 -1
- package/examples/case-insensitive-path-guard.sh +21 -2
- package/examples/case-sensitive-guard.sh +23 -2
- package/examples/cch-cache-guard.sh +0 -0
- package/examples/cch-sentinel-precommit-guard.sh +47 -0
- package/examples/check-abort-controller.sh +1 -1
- package/examples/check-accessibility.sh +0 -0
- package/examples/check-aria-labels.sh +0 -0
- package/examples/check-before-act-enforcer.sh +12 -0
- package/examples/check-charset-meta.sh +0 -0
- package/examples/check-cookie-flags.sh +0 -0
- package/examples/check-cors-config.sh +0 -0
- package/examples/check-csp-headers.sh +0 -0
- package/examples/check-csrf-protection.sh +0 -0
- package/examples/check-debounce.sh +1 -1
- package/examples/check-dependency-age.sh +0 -0
- package/examples/check-dependency-license.sh +0 -0
- package/examples/check-dockerfile-best-practice.sh +0 -0
- package/examples/check-error-boundaries.sh +0 -0
- package/examples/check-error-class.sh +1 -1
- package/examples/check-error-handling.sh +0 -0
- package/examples/check-error-logging.sh +1 -1
- package/examples/check-error-message.sh +0 -0
- package/examples/check-error-stack.sh +0 -0
- package/examples/check-favicon.sh +0 -0
- package/examples/check-git-hooks-compat.sh +0 -0
- package/examples/check-gitattributes.sh +0 -0
- package/examples/check-https-redirect.sh +0 -0
- package/examples/check-input-validation.sh +0 -0
- package/examples/check-lang-attribute.sh +0 -0
- package/examples/check-npm-scripts-exist.sh +0 -0
- package/examples/check-package-size.sh +0 -0
- package/examples/check-port-availability.sh +0 -0
- package/examples/check-promise-all.sh +1 -1
- package/examples/check-rate-limiting.sh +0 -0
- package/examples/check-return-types.sh +0 -0
- package/examples/check-semantic-versioning.sh +0 -0
- package/examples/check-suspense-fallback.sh +1 -1
- package/examples/check-test-exists.sh +0 -0
- package/examples/check-test-naming.sh +0 -0
- package/examples/check-timeout-cleanup.sh +1 -1
- package/examples/check-tls-version.sh +0 -0
- package/examples/check-unsubscribe.sh +1 -1
- package/examples/check-viewport-meta.sh +0 -0
- package/examples/check-worker-terminate.sh +1 -1
- package/examples/checkpoint-tamper-guard.sh +12 -0
- package/examples/chmod-guard.sh +12 -0
- package/examples/chown-guard.sh +24 -0
- package/examples/ci-workflow-guard.sh +6 -1
- package/examples/claim-verify-detector.sh +109 -0
- package/examples/claim-vs-caveat-checker.sh +77 -0
- package/examples/classifier-fallback-allow.sh +114 -40
- package/examples/claude-cache-gc.sh +1 -0
- package/examples/claude-code-version-pin-advisor.sh +183 -0
- package/examples/claude-md-reinjector.sh +129 -0
- package/examples/claude-md-size-monitor.sh +66 -0
- package/examples/claude-update-budget-guard.sh +123 -0
- package/examples/claude-update-smart.sh +113 -0
- package/examples/claudeignore-enforce-guard.sh +12 -0
- package/examples/claudemd-enforcer.sh +0 -0
- package/examples/claudemd-tool-prohibition.sh +128 -0
- package/examples/clear-command-confirm-guard.sh +32 -15
- package/examples/cli-config-pinning-detector.sh +162 -0
- package/examples/cliff-countdown-advisor.sh +96 -0
- package/examples/clipboard-secret-guard.sh +12 -0
- package/examples/closure-word-verify-gate.sh +150 -0
- package/examples/cloud-cli-guard.sh +39 -2
- package/examples/commit-all-scope-guard.sh +44 -0
- package/examples/commit-message-check.sh +1 -1
- package/examples/commit-message-quality.sh +6 -1
- package/examples/commitment-carry-forward-arrest.sh +361 -0
- package/examples/compact-alert-notification.sh +0 -0
- package/examples/compact-dispatch-watchdog.sh +149 -0
- package/examples/completion-claim-without-verification-detector.sh +207 -0
- package/examples/composer-guard.sh +12 -0
- package/examples/compound-bash-permission-resolver.sh +156 -0
- package/examples/compound-command-allow.sh +1 -1
- package/examples/compound-command-deny-enforcer.sh +183 -0
- package/examples/compound-inject-guard.sh +12 -0
- package/examples/concurrent-edit-lock.sh +12 -0
- package/examples/conflict-marker-guard.sh +12 -0
- package/examples/consecutive-error-breaker.sh +0 -0
- package/examples/console-log-count.sh +1 -0
- package/examples/context-compact-advisor.sh +29 -2
- package/examples/context-length-budget.sh +69 -0
- package/examples/context-threshold-alert.sh +12 -0
- package/examples/context-usage-drift-alert.sh +41 -13
- package/examples/conversation-history-guard.sh +12 -0
- package/examples/core-file-protect-guard.sh +12 -0
- package/examples/cors-star-warn.sh +0 -0
- package/examples/cost-incident-self-audit.sh +162 -0
- package/examples/cowork-claude-md-load-checker.sh +100 -0
- package/examples/cowork-fuse-staleness-watcher.sh +140 -0
- package/examples/cowork-hook-absence-warner.sh +167 -0
- package/examples/cowork-model-picker-advisor.sh +115 -0
- package/examples/credential-exfil-guard.sh +65 -4
- package/examples/credential-file-cat-guard.sh +17 -1
- package/examples/cron-create-receipt.sh +112 -0
- package/examples/cron-modification-guard.sh +12 -0
- package/examples/cross-product-mcp-spawn-detector.sh +178 -0
- package/examples/cwd-project-boundary-guard.sh +0 -0
- package/examples/daemon-zombie-worker-surfacer.sh +118 -0
- package/examples/daily-cost-guard.sh +164 -0
- package/examples/daily-usage-tracker.sh +0 -0
- package/examples/dangerous-pip-flag-guard.sh +12 -0
- package/examples/db-connect-guard.sh +13 -1
- package/examples/denied-action-retry-guard.sh +12 -0
- package/examples/deny-bypass-detector.sh +12 -0
- package/examples/deny-rule-integrity-verifier.sh +181 -0
- package/examples/dependency-install-guard.sh +12 -0
- package/examples/deploy-guard.sh +14 -2
- package/examples/deploy-path-verify-guard.sh +12 -0
- package/examples/deployment-readback-gate.sh +135 -0
- package/examples/deployment-readback-gh-adapter.sh +247 -0
- package/examples/deployment-verify-guard.sh +25 -2
- package/examples/destructive-db-script-write-guard.sh +166 -0
- package/examples/destructive-migration-write-guard.sh +163 -0
- package/examples/diff-size-guard.sh +12 -0
- package/examples/disabled-feature-toggle-advisor.sh +88 -0
- package/examples/disk-partition-guard.sh +12 -0
- package/examples/dispatch-allowlist-preflight.sh +301 -0
- package/examples/dispatch-liveness-watchdog.sh +216 -0
- package/examples/dispatch-receipt.sh +174 -0
- package/examples/django-migrate-guard.sh +12 -0
- package/examples/dns-config-guard.sh +12 -0
- package/examples/docker-dangerous-guard.sh +12 -0
- package/examples/docker-volume-guard.sh +0 -0
- package/examples/dockerfile-latest-guard.sh +1 -0
- package/examples/dotenv-anthropic-key-billing-guard.sh +99 -0
- package/examples/dotenv-commit-guard.sh +12 -0
- package/examples/dotenv-read-guard.sh +12 -0
- package/examples/dotfile-protection-guard.sh +12 -0
- package/examples/dotnet-build-on-edit.sh +1 -1
- package/examples/drizzle-migrate-guard.sh +27 -2
- package/examples/echo-probe-spam-detector.sh +176 -0
- package/examples/edit-counter-test-gate.sh +12 -0
- package/examples/edit-error-counter.sh +1 -1
- package/examples/edit-guard.sh +12 -0
- package/examples/edit-old-string-validator.sh +12 -0
- package/examples/edit-quote-ambiguity-guard.sh +97 -0
- package/examples/edit-retry-loop-guard.sh +0 -0
- package/examples/edit-verify.sh +0 -0
- package/examples/env-inline-secret-guard.sh +14 -2
- package/examples/env-naming-convention.sh +0 -0
- package/examples/env-prod-guard.sh +0 -0
- package/examples/env-required-check.sh +0 -0
- package/examples/env-source-guard.sh +12 -0
- package/examples/env-var-check.sh +24 -1
- package/examples/ephemeral-container-detector.sh +147 -0
- package/examples/error-memory-guard.sh +12 -0
- package/examples/evidence-claim-gate.sh +187 -0
- package/examples/exploration-budget-guard.sh +12 -0
- package/examples/expo-eject-guard.sh +13 -0
- package/examples/extended-thinking-loop-guard.sh +139 -0
- package/examples/extended-thinking-resume-warning.sh +119 -0
- package/examples/extended-thinking-tool-use-mismatch-detector.sh +212 -0
- package/examples/fabricated-command-detector.sh +145 -0
- package/examples/false-disk-full-guard.sh +63 -0
- package/examples/feature-deprecation-detector.sh +109 -0
- package/examples/file-change-tracker.sh +1 -1
- package/examples/file-change-undo-tracker.sh +0 -0
- package/examples/file-edit-backup.sh +63 -14
- package/examples/file-reference-check.sh +0 -0
- package/examples/file-size-limit.sh +12 -0
- package/examples/financial-operation-guard.sh +12 -0
- package/examples/firewall-guard.sh +12 -0
- package/examples/fish-shell-wrapper.sh +125 -7
- package/examples/five-hundred-milestone.sh +1 -0
- package/examples/flask-static-route-guard.sh +89 -0
- package/examples/forbidden-response-phrase-detector.sh +161 -0
- package/examples/gem-push-guard.sh +13 -0
- package/examples/gh-cli-destructive-guard.sh +13 -1
- package/examples/git-checkout-safety-guard.sh +12 -0
- package/examples/git-checkout-uncommitted-guard.sh +12 -0
- package/examples/git-config-guard.sh +12 -0
- package/examples/git-crypt-worktree-guard.sh +12 -0
- package/examples/git-filter-repo-guard.sh +56 -0
- package/examples/git-history-rewrite-guard.sh +12 -0
- package/examples/git-hook-bypass-guard.sh +0 -0
- package/examples/git-maintenance-guard.sh +83 -0
- package/examples/git-merge-conflict-prevent.sh +0 -0
- package/examples/git-message-length-check.sh +0 -0
- package/examples/git-message-length.sh +0 -0
- package/examples/git-operations-require-approval.sh +68 -14
- package/examples/git-pack-temp-cleanup-guard.sh +102 -0
- package/examples/git-push-blast-radius-guard.sh +218 -0
- package/examples/git-remote-guard.sh +24 -3
- package/examples/git-rm-orphan-wipe-guard.sh +85 -0
- package/examples/git-stash-before-checkout.sh +12 -0
- package/examples/git-stash-before-danger.sh +0 -0
- package/examples/git-submodule-guard.sh +69 -2
- package/examples/git-tag-guard.sh +12 -0
- package/examples/github-actions-secret-guard.sh +0 -0
- package/examples/gitignore-check.sh +0 -0
- package/examples/gitops-drift-guard.sh +12 -0
- package/examples/go-mod-tidy-warn.sh +1 -0
- package/examples/go-vet-after-edit.sh +12 -0
- package/examples/goal-iteration-limit-warner.sh +152 -0
- package/examples/grep-nul-false-negative-guard.sh +30 -0
- package/examples/growthbook-flag-monitor.sh +257 -0
- package/examples/hallucination-url-check.sh +1 -1
- package/examples/halt-signal-detector.sh +135 -0
- package/examples/handoff-on-clear.sh +65 -0
- package/examples/hardcoded-ip-guard.sh +1 -0
- package/examples/headless-empty-result-guard.sh +0 -0
- package/examples/headless-stop-guard.sh +0 -0
- package/examples/helm-install-guard.sh +2 -1
- package/examples/home-critical-bash-guard.sh +17 -1
- package/examples/hook-debug-wrapper.sh +6 -2
- package/examples/hook-permission-fixer.sh +0 -0
- package/examples/hook-self-disable-detector.sh +99 -0
- package/examples/hook-stdout-sanitizer.sh +6 -2
- package/examples/hook-tamper-guard.sh +12 -0
- package/examples/idle-session-cost-alert.sh +0 -0
- package/examples/image-dimension-guard.sh +109 -0
- package/examples/image-file-validator.sh +0 -0
- package/examples/iteration-quality-degradation-detector.sh +170 -0
- package/examples/java-compile-on-edit.sh +1 -1
- package/examples/json-syntax-check.sh +0 -0
- package/examples/k8s-production-guard.sh +13 -1
- package/examples/kill-process-guard.sh +12 -0
- package/examples/kubernetes-guard.sh +13 -1
- package/examples/laravel-artisan-guard.sh +13 -0
- package/examples/large-file-guard.sh +1 -1
- package/examples/log-level-guard.sh +0 -0
- package/examples/log-truncation-guard.sh +12 -0
- package/examples/long-session-malformed-tool-call-detector.sh +183 -0
- package/examples/loop-detector.sh +12 -0
- package/examples/magic-number-warn.sh +1 -0
- package/examples/main-branch-warn.sh +12 -0
- package/examples/markdown-link-check.sh +0 -0
- package/examples/max-concurrent-agents.sh +12 -0
- package/examples/max-edit-size-guard.sh +13 -0
- package/examples/max-file-count-guard.sh +0 -0
- package/examples/max-file-delete-count.sh +0 -0
- package/examples/max-function-length.sh +1 -0
- package/examples/max-import-count.sh +0 -0
- package/examples/max-subagent-count.sh +0 -0
- package/examples/mcp-config-freeze.sh +12 -0
- package/examples/mcp-config-poisoning-audit.sh +150 -0
- package/examples/mcp-data-boundary.sh +1 -1
- package/examples/mcp-misdiagnosis-arrest.sh +209 -0
- package/examples/mcp-orphan-leak-warner.sh +49 -0
- package/examples/mcp-permissions-ask-warner.sh +151 -0
- package/examples/mcp-routine-approval-detector.sh +154 -0
- package/examples/mcp-server-allowlist.sh +12 -0
- package/examples/mcp-server-guard.sh +12 -0
- package/examples/mcp-startup-bloat-detector.sh +87 -0
- package/examples/mcp-stdio-compatibility-test.sh +153 -0
- package/examples/mcp-tool-audit-log.sh +0 -0
- package/examples/mcp-tool-guard.sh +101 -1
- package/examples/mcp-warmup-wait.sh +0 -0
- package/examples/memory-chain-audit.sh +56 -0
- package/examples/memory-orphan-detector.sh +188 -0
- package/examples/memory-write-guard.sh +99 -17
- package/examples/migration-verify-guard.sh +12 -0
- package/examples/model-swap-suggester.sh +177 -0
- package/examples/model-version-alert.sh +5 -1
- package/examples/model-version-lock.sh +63 -0
- package/examples/move-delete-sequence-guard.sh +33 -2
- package/examples/multi-file-plan-routing-gate.sh +192 -0
- package/examples/multi-vendor-concurrent-warner.sh +108 -0
- package/examples/multi-window-auth-drift-detector.sh +183 -0
- package/examples/multiline-command-approver.sh +161 -23
- package/examples/nested-background-agent-guard.sh +109 -0
- package/examples/nested-spawn-inflight-guard.sh +178 -0
- package/examples/network-exfil-guard.sh +12 -0
- package/examples/network-guard.sh +12 -0
- package/examples/network-interface-guard.sh +12 -0
- package/examples/nextjs-env-guard.sh +1 -1
- package/examples/no-absolute-import.sh +0 -0
- package/examples/no-alert-confirm-prompt.sh +0 -0
- package/examples/no-anonymous-default-export.sh +0 -0
- package/examples/no-any-type.sh +0 -0
- package/examples/no-any-typescript.sh +1 -0
- package/examples/no-ask-human.sh +12 -0
- package/examples/no-assignment-in-condition.sh +0 -0
- package/examples/no-base64-exfil.sh +12 -0
- package/examples/no-callback-hell.sh +0 -0
- package/examples/no-circular-dependency.sh +0 -0
- package/examples/no-cleartext-storage.sh +0 -0
- package/examples/no-commented-code.sh +0 -0
- package/examples/no-commit-fixup.sh +0 -0
- package/examples/no-console-assert.sh +0 -0
- package/examples/no-console-error-swallow.sh +0 -0
- package/examples/no-console-in-prod.sh +0 -0
- package/examples/no-console-log-commit.sh +12 -0
- package/examples/no-console-log.sh +0 -0
- package/examples/no-console-time.sh +0 -0
- package/examples/no-cors-wildcard.sh +4 -1
- package/examples/no-curl-upload.sh +0 -0
- package/examples/no-dangerouslySetInnerHTML.sh +0 -0
- package/examples/no-dangling-await.sh +1 -0
- package/examples/no-debug-commit.sh +12 -0
- package/examples/no-debug-in-commit.sh +0 -0
- package/examples/no-deep-nesting.sh +0 -0
- package/examples/no-deep-relative-import.sh +1 -0
- package/examples/no-default-credentials.sh +0 -0
- package/examples/no-deploy-friday.sh +13 -1
- package/examples/no-disabled-test.sh +0 -0
- package/examples/no-document-write.sh +0 -0
- package/examples/no-empty-function.sh +0 -0
- package/examples/no-eval-in-template.sh +0 -0
- package/examples/no-eval-template.sh +3 -1
- package/examples/no-eval.sh +0 -0
- package/examples/no-exec-user-input.sh +0 -0
- package/examples/no-fixme-ship.sh +12 -0
- package/examples/no-floating-promises.sh +0 -0
- package/examples/no-force-flag.sh +22 -5
- package/examples/no-force-install.sh +0 -0
- package/examples/no-git-amend.sh +12 -0
- package/examples/no-git-rebase-public.sh +0 -0
- package/examples/no-global-install.sh +12 -0
- package/examples/no-global-state.sh +0 -0
- package/examples/no-hardcoded-port.sh +1 -0
- package/examples/no-hardcoded-url.sh +0 -0
- package/examples/no-helmet-missing.sh +0 -0
- package/examples/no-http-url.sh +1 -0
- package/examples/no-http-without-https.sh +0 -0
- package/examples/no-inline-style.sh +0 -0
- package/examples/no-inline-styles.sh +1 -0
- package/examples/no-innerhtml.sh +0 -0
- package/examples/no-install-global.sh +12 -0
- package/examples/no-jwt-in-url.sh +0 -0
- package/examples/no-large-commit.sh +0 -0
- package/examples/no-localhost-expose.sh +0 -0
- package/examples/no-magic-number.sh +0 -0
- package/examples/no-md5-sha1.sh +0 -0
- package/examples/no-mixed-line-endings.sh +8 -1
- package/examples/no-mutation-in-reducer.sh +0 -0
- package/examples/no-nested-ternary.sh +0 -0
- package/examples/no-network-exfil.sh +0 -0
- package/examples/no-open-redirect.sh +0 -0
- package/examples/no-output-truncation.sh +12 -0
- package/examples/no-package-downgrade.sh +0 -0
- package/examples/no-package-lock-edit.sh +12 -0
- package/examples/no-path-join-user-input.sh +0 -0
- package/examples/no-port-bind.sh +0 -0
- package/examples/no-process-exit.sh +0 -0
- package/examples/no-prototype-pollution.sh +0 -0
- package/examples/no-push-without-ci.sh +0 -0
- package/examples/no-push-without-tests.sh +12 -0
- package/examples/no-raw-password-in-url.sh +0 -0
- package/examples/no-root-user-docker.sh +1 -0
- package/examples/no-root-write.sh +12 -0
- package/examples/no-secrets-in-args.sh +4 -1
- package/examples/no-secrets-in-logs.sh +0 -0
- package/examples/no-sensitive-log.sh +0 -0
- package/examples/no-sleep-in-hooks.sh +0 -0
- package/examples/no-star-import-python.sh +1 -0
- package/examples/no-string-concat-sql.sh +0 -0
- package/examples/no-sudo-guard.sh +12 -0
- package/examples/no-sync-fs.sh +0 -0
- package/examples/no-todo-in-merge.sh +0 -0
- package/examples/no-todo-in-production.sh +1 -0
- package/examples/no-todo-without-issue.sh +0 -0
- package/examples/no-unused-import.sh +0 -0
- package/examples/no-var-keyword.sh +0 -0
- package/examples/no-verify-blocker.sh +12 -0
- package/examples/no-wget-piped-bash.sh +12 -0
- package/examples/no-wildcard-cors.sh +0 -0
- package/examples/no-wildcard-delete.sh +0 -0
- package/examples/no-wildcard-import.sh +0 -0
- package/examples/no-with-statement.sh +0 -0
- package/examples/no-write-outside-src.sh +0 -0
- package/examples/no-xml-external-entity.sh +0 -0
- package/examples/non-english-quality-warner.sh +156 -0
- package/examples/notify-waiting.sh +1 -1
- package/examples/npm-audit-warn.sh +0 -0
- package/examples/npm-global-install-guard.sh +12 -0
- package/examples/npm-publish-guard.sh +12 -0
- package/examples/npm-script-injection.sh +0 -0
- package/examples/npm-supply-chain-guard.sh +0 -0
- package/examples/nuxt-config-guard.sh +1 -0
- package/examples/oauth-refresh-monitor.sh +210 -0
- package/examples/opus-degradation-tracker.sh +187 -0
- package/examples/opus48-routine-task-warning.sh +196 -0
- package/examples/opus48-thinking-wedge-advisor.sh +143 -0
- package/examples/output-credential-scan.sh +1 -1
- package/examples/output-secret-mask.sh +31 -9
- package/examples/output-token-spike-detector.sh +145 -0
- package/examples/package-json-guard.sh +12 -0
- package/examples/package-lock-frozen.sh +12 -0
- package/examples/parallel-batch-size-limiter.sh +121 -0
- package/examples/parallel-cascade-detector.sh +116 -0
- package/examples/partial-view-claim-arrest.sh +174 -0
- package/examples/path-deny-bash-guard.sh +12 -0
- package/examples/path-traversal-guard.sh +12 -0
- package/examples/per-prompt-token-cap.sh +124 -0
- package/examples/permission-audit-log.sh +1 -1
- package/examples/permission-denial-enforcer.sh +12 -0
- package/examples/permission-entry-validator.sh +0 -0
- package/examples/persisted-1m-model-advisor.sh +88 -0
- package/examples/php-lint-on-edit.sh +1 -1
- package/examples/pii-upload-guard.sh +12 -0
- package/examples/pip-publish-guard.sh +13 -0
- package/examples/pip-requirements-guard.sh +12 -0
- package/examples/pip-venv-required.sh +12 -0
- package/examples/plan-mode-edit-guard.sh +12 -0
- package/examples/plan-mode-enforcer.sh +12 -0
- package/examples/plan-mode-strict-guard.sh +12 -0
- package/examples/plugin-hooks-json-bloat-detector.sh +169 -0
- package/examples/plugin-process-cleanup.sh +0 -0
- package/examples/polyglot-rm-guard.sh +12 -0
- package/examples/post-compact-safety.sh +12 -0
- package/examples/post-edit-disk-verify.sh +152 -0
- package/examples/powershell-remove-item-guard.sh +85 -0
- package/examples/pr-description-check.sh +0 -0
- package/examples/pr-duplicate-guard.sh +13 -0
- package/examples/pre-bash-sed-line-ending-windows.sh +87 -0
- package/examples/pre-compact-knowledge-save.sh +0 -0
- package/examples/pre-compact-transcript-backup.sh +0 -0
- package/examples/pre-execution-claim-detector.sh +179 -0
- package/examples/prefer-builtin-tools.sh +10 -1
- package/examples/prefer-const.sh +0 -0
- package/examples/prefer-dedicated-tools.sh +12 -0
- package/examples/prefer-optional-chaining.sh +0 -0
- package/examples/prisma-migrate-guard.sh +24 -7
- package/examples/production-port-kill-guard.sh +12 -0
- package/examples/prompt-injection-guard.sh +2 -1
- package/examples/prompt-usage-logger.sh +0 -0
- package/examples/protect-claudemd.sh +12 -0
- package/examples/protect-dotfiles.sh +12 -0
- package/examples/proxy-capture-suggester.sh +159 -0
- package/examples/public-artefact-socratic-narrowing.sh +232 -0
- package/examples/public-repo-push-guard.sh +12 -0
- package/examples/push-requires-test-pass-record.sh +0 -0
- package/examples/push-requires-test-pass.sh +12 -0
- package/examples/quota-anomaly-detector.sh +173 -0
- package/examples/quota-reset-audit.sh +58 -0
- package/examples/quoted-flag-approver.sh +99 -10
- package/examples/rails-migration-guard.sh +12 -0
- package/examples/rate-limit-guard.sh +0 -0
- package/examples/read-all-files-enforcer.sh +0 -0
- package/examples/read-budget-guard.sh +12 -0
- package/examples/read-loop-detector.sh +59 -0
- package/examples/read-once-guard.sh +96 -0
- package/examples/read-only-mode.sh +12 -0
- package/examples/readme-exists-check.sh +0 -0
- package/examples/record-read-coverage.sh +73 -0
- package/examples/redirect-fragment-warner.sh +149 -0
- package/examples/redis-flushall-guard.sh +13 -0
- package/examples/redundant-read-blocker.sh +132 -0
- package/examples/refusal-arrest-gate.sh +248 -0
- package/examples/registry-publish-guard.sh +13 -1
- package/examples/remote-control-billing-classifier.sh +135 -0
- package/examples/replace-all-guard.sh +12 -0
- package/examples/repo-visibility-guard.sh +12 -0
- package/examples/reroute-after-block-guard.sh +150 -0
- package/examples/response-budget-guard.sh +0 -0
- package/examples/resume-drift-watcher.sh +57 -0
- package/examples/rg-replace-flag-detector.sh +125 -0
- package/examples/rhetorical-verification-prompt-detector.sh +102 -0
- package/examples/ripgrep-permission-fix.sh +0 -0
- package/examples/rm-safety-net.sh +151 -8
- package/examples/role-tool-guard.sh +12 -0
- package/examples/route-handler-emptiness-gate.sh +324 -0
- package/examples/ruby-lint-on-edit.sh +1 -1
- package/examples/runtime-binary-change-detector.sh +102 -0
- package/examples/same-command-repeat-detector.sh +196 -0
- package/examples/same-correction-arrest.sh +169 -0
- package/examples/sandbox-denywrite-enforcer.sh +78 -0
- package/examples/sandbox-relative-path-audit.sh +83 -25
- package/examples/sandbox-write-verify.sh +12 -0
- package/examples/schema-migration-guard.sh +0 -0
- package/examples/scope-expansion-receipt.sh +178 -0
- package/examples/scope-guard.sh +88 -9
- package/examples/secret-file-read-guard.sh +12 -0
- package/examples/secret-file-write-guard.sh +150 -0
- package/examples/self-modify-bypass-guard.sh +0 -0
- package/examples/sensitive-file-read-guard.sh +23 -3
- package/examples/sensitive-log-guard.sh +1 -0
- package/examples/server-side-prompt-injection-detector.sh +69 -0
- package/examples/session-agent-cost-limiter.sh +12 -0
- package/examples/session-backup-on-start.sh +1 -1
- package/examples/session-cost-alert.sh +12 -0
- package/examples/session-drift-guard.sh +12 -0
- package/examples/session-duration-guard.sh +25 -2
- package/examples/session-end-logger.sh +0 -0
- package/examples/session-health-monitor.sh +0 -0
- package/examples/session-index-repair.sh +1 -1
- package/examples/session-memory-watchdog.sh +1 -0
- package/examples/session-permission-reset-guard.sh +12 -0
- package/examples/session-persistence-verifier.sh +93 -0
- package/examples/session-plugin-pin-watch.sh +68 -0
- package/examples/session-rate-monitor.sh +176 -0
- package/examples/session-resume-env-fix.sh +0 -0
- package/examples/session-start-quota-status.sh +193 -0
- package/examples/session-start-safety-check.sh +55 -3
- package/examples/session-state-saver.sh +0 -0
- package/examples/session-summary-stop.sh +1 -1
- package/examples/session-summary.sh +0 -0
- package/examples/session-token-counter.sh +1 -1
- package/examples/settings-hooks-key-restorer.sh +99 -0
- package/examples/settings-json-health-check.sh +57 -0
- package/examples/settings-json-model-guard.sh +0 -0
- package/examples/settings-regression-tester.sh +188 -0
- package/examples/shell-config-truncation-guard.sh +12 -0
- package/examples/shell-wrapper-guard.sh +12 -0
- package/examples/skill-cumulative-size-detector.sh +104 -0
- package/examples/skill-description-drop-detector.sh +148 -0
- package/examples/skill-gate.sh +0 -0
- package/examples/skill-truncation-detector.sh +154 -0
- package/examples/skills-context-recorder.sh +167 -0
- package/examples/skills-load-verifier.sh +96 -0
- package/examples/skills-settings-validator.sh +139 -0
- package/examples/sonnet-45-deprecation-helper.sh +85 -0
- package/examples/spec-file-scope-guard.sh +12 -0
- package/examples/spring-profile-guard.sh +1 -0
- package/examples/spurious-malformed-notice-detector.sh +247 -0
- package/examples/sql-bulk-delete-warn.sh +88 -0
- package/examples/sql-injection-detect.sh +0 -0
- package/examples/ssh-key-protect.sh +12 -0
- package/examples/staged-secret-scan.sh +22 -1
- package/examples/stale-temp-settings-detector.sh +86 -0
- package/examples/standing-rule-session-surfacer.sh +137 -0
- package/examples/stop-hook-sigterm-wrapper.sh +182 -0
- package/examples/stop-transcript-write-health.sh +64 -0
- package/examples/strict-allowlist.sh +57 -15
- package/examples/strip-coauthored-by.sh +50 -10
- package/examples/subagent-blast-radius-guard.sh +184 -0
- package/examples/subagent-boundary-precheck.sh +126 -0
- package/examples/subagent-budget-guard.sh +12 -0
- package/examples/subagent-claudemd-inject.sh +0 -0
- package/examples/subagent-closure-verify-gate.sh +164 -0
- package/examples/subagent-destructive-git-guard.sh +120 -0
- package/examples/subagent-error-detector.sh +0 -0
- package/examples/subagent-forged-system-reminder-guard.sh +156 -0
- package/examples/subagent-identity-leak-guard.sh +102 -0
- package/examples/subagent-identity-reassertion.sh +51 -0
- package/examples/subagent-inheritance-tester.sh +179 -0
- package/examples/subagent-permission-mode-guard.sh +110 -0
- package/examples/subagent-scope-guard.sh +12 -0
- package/examples/subagent-spawn-verification-enforcer.sh +102 -0
- package/examples/subagent-tool-allowlist-enforcer.sh +101 -0
- package/examples/subagent-tool-call-limiter.sh +87 -15
- package/examples/subcommand-chain-guard.sh +12 -0
- package/examples/subscription-api-billing-warner.sh +160 -0
- package/examples/subscription-bypass-detector.sh +152 -0
- package/examples/svelte-lint-on-edit.sh +1 -0
- package/examples/swift-build-on-edit.sh +1 -1
- package/examples/symlink-guard.sh +27 -2
- package/examples/symlink-protect.sh +1 -0
- package/examples/system-dir-protection-guard.sh +73 -8
- package/examples/system-message-workaround.sh +38 -13
- package/examples/system-package-guard.sh +12 -0
- package/examples/systemd-service-guard.sh +12 -0
- package/examples/task-integrity-guard.sh +12 -0
- package/examples/temp-file-cleanup.sh +1 -1
- package/examples/temporal-suggestion-detector.sh +135 -0
- package/examples/terraform-guard.sh +27 -6
- package/examples/test-after-edit.sh +1 -1
- package/examples/test-before-push.sh +12 -0
- package/examples/test-coverage-reminder.sh +24 -1
- package/examples/thinking-budget-effort-mismatch-detector.sh +149 -0
- package/examples/timezone-guard.sh +0 -0
- package/examples/tmp-output-size-guard.sh +0 -0
- package/examples/todo-check.sh +1 -1
- package/examples/token-budget-guard.sh +12 -0
- package/examples/token-budget-per-task.sh +12 -0
- package/examples/token-usage-tracker.sh +7 -1
- package/examples/tokenizer-ratio-alert-corpus.sh +90 -0
- package/examples/tokenizer-ratio-alert.sh +104 -0
- package/examples/tool-call-rate-limiter.sh +0 -0
- package/examples/tool-result-correlation-checker.sh +167 -0
- package/examples/tool-result-size-guard.sh +132 -0
- package/examples/tool-retry-budget-guard.sh +12 -0
- package/examples/transcript-contamination-detector.sh +138 -0
- package/examples/trustfall-mcp-injection-guard.sh +103 -0
- package/examples/ultrareview-large-diff-advisor.sh +184 -0
- package/examples/unbounded-output-guard.sh +94 -0
- package/examples/uncommitted-changes-stop.sh +1 -0
- package/examples/uncommitted-discard-guard.sh +23 -5
- package/examples/uncommitted-work-guard.sh +12 -0
- package/examples/usage-warn.sh +0 -0
- package/examples/user-account-guard.sh +12 -0
- package/examples/userprompt-submit-receipt.sh +123 -0
- package/examples/variable-expansion-guard.sh +12 -0
- package/examples/verify-after-publish-reminder.sh +93 -0
- package/examples/verify-before-commit.sh +12 -0
- package/examples/version-bump-detector.sh +156 -0
- package/examples/version-regression-warner.sh +144 -0
- package/examples/vue-lint-on-edit.sh +1 -0
- package/examples/warn-cron-cost-trap.sh +173 -0
- package/examples/webfetch-runaway-guard.sh +89 -0
- package/examples/wellness-break-reminder.sh +118 -0
- package/examples/windows-destructive-command-guard.sh +177 -0
- package/examples/windows-path-guard.sh +12 -0
- package/examples/windows-python-stub-detector.sh +63 -0
- package/examples/work-hours-guard.sh +12 -0
- package/examples/working-directory-fence.sh +12 -0
- package/examples/workspace-lease-guard.sh +205 -0
- package/examples/worktree-create-log.sh +1 -0
- package/examples/worktree-delete-guard.sh +12 -0
- package/examples/worktree-edit-boundary-guard.sh +127 -0
- package/examples/worktree-escape-write-guard.sh +114 -0
- package/examples/worktree-hook-linker.sh +0 -0
- package/examples/worktree-hooks-path-fix.sh +111 -0
- package/examples/worktree-parent-write-guard.sh +43 -0
- package/examples/worktree-project-unify.sh +2 -1
- package/examples/worktree-remove-uncommitted-guard.sh +13 -0
- package/examples/worktree-unmerged-guard.sh +7 -1
- package/examples/write-byte-integrity-verifier.sh +190 -0
- package/examples/write-empty-content-guard.sh +67 -0
- package/examples/write-nul-corruption-detector.sh +61 -0
- package/examples/write-overwrite-confirm.sh +160 -14
- package/examples/write-secret-guard.sh +27 -5
- package/examples/write-shrink-guard.sh +12 -0
- package/examples/write-test-ratio.sh +0 -0
- package/examples/wsl-host-disk-space-guard.sh +97 -0
- package/examples/xml-format-leak-detector.sh +266 -0
- package/examples/yaml-syntax-check.sh +12 -0
- package/hooks/hooks.json +6 -6
- package/index.mjs +1699 -183
- package/mission.md +2 -0
- package/package.json +4 -4
- package/plugins/credential-guard/.claude-plugin/plugin.json +9 -7
- package/plugins/git-protection/.claude-plugin/plugin.json +10 -8
- package/plugins/safety-essentials/.claude-plugin/plugin.json +9 -7
- package/plugins/token-guard/.claude-plugin/plugin.json +10 -8
- package/scripts/agents-md-sync-setup.sh +156 -0
- package/scripts/autonomy-blocked-summary.sh +148 -0
- package/scripts/build-search-index.py +43 -0
- package/scripts/build-sitemap.py +119 -0
- package/scripts/cc-doctor.sh +192 -0
- package/scripts/check-hook-event-names.py +127 -0
- package/scripts/check-misfire-instrument.sh +64 -0
- package/scripts/claim-verify-audit.sh +467 -0
- package/scripts/cowork-claudemd-helper.sh +136 -0
- package/scripts/june-15-deprecated-model-scan.sh +111 -0
- package/scripts/measure-heredoc-shapes.sh +67 -0
- package/scripts/measure-literal-match-misfire.sh +110 -0
- package/scripts/probe-scope-guard-branches.sh +48 -0
- package/scripts/probe-skip-line-both-ways.sh +65 -0
- package/scripts/receipts-aggregate.py +199 -0
- package/scripts/session-forensic-audit.py +360 -0
- package/scripts.json +9 -9
- package/scripts.json.bak-2026-07-27-find +13 -0
- package/skills/safety-setup/SKILL.md +5 -5
- package/tests/approve-side-remaining-two.test.sh +129 -0
- package/tests/approver-list-granularity.test.sh +145 -0
- package/tests/askuserquestion-autonomy-gate.test.sh +181 -0
- package/tests/audit-ci-gate.test.sh +87 -0
- package/tests/audit-cross-layer-claudemd.test.sh +170 -0
- package/tests/audit-fail-open-parse.test.sh +100 -0
- package/tests/auto-approve-compound-tail.test.sh +194 -0
- package/tests/auto-mode-path-invoked-commands.test.sh +89 -0
- package/tests/auto-mode-quoted-targets.test.sh +127 -0
- package/tests/auto-mode-unquoted-targets.test.sh +112 -0
- package/tests/bash-secret-output-detector-detects.test.sh +102 -0
- package/tests/blindspots-cross-layer.test.sh +177 -0
- package/tests/block-database-wipe.test.sh +64 -0
- package/tests/bundled-short-flags-bypass.test.sh +85 -0
- package/tests/cd-git-allow-compound-tail.test.sh +67 -0
- package/tests/chown-guard-filesystem-root.test.sh +64 -0
- package/tests/ci-workflow-guard-skip-rule.test.sh +115 -0
- package/tests/compound-deny-safe-rm-targets.test.sh +105 -0
- package/tests/core-scripts-parser-fallback.test.sh +140 -0
- package/tests/destructive-guard-bare-glob.test.sh +74 -0
- package/tests/destructive-guard-every-operand.test.sh +100 -0
- package/tests/destructive-guard-find-deletion.test.sh +114 -0
- package/tests/destructive-guard-flag-order.test.sh +106 -0
- package/tests/destructive-guard-mentions-vs-invocations.test.sh +107 -0
- package/tests/destructive-guard-quoted-target.test.sh +89 -0
- package/tests/destructive-guard-separators.test.sh +105 -0
- package/tests/destructive-guard-variable-target.test.sh +98 -0
- package/tests/destructive-guard-wrapped-command.test.sh +91 -0
- package/tests/doctor-hook-disabling-env.test.sh +92 -0
- package/tests/doctor-misspelled-settings-keys.test.sh +106 -0
- package/tests/example-guards-wrapped-command.test.sh +169 -0
- package/tests/file-edit-backup.test.sh +93 -0
- package/tests/git-filter-repo-guard.test.sh +60 -0
- package/tests/git-global-options-bypass.test.sh +141 -0
- package/tests/git-invocation-prefixes-all-guards.test.sh +114 -0
- package/tests/git-maintenance-guard.test.sh +83 -0
- package/tests/git-pack-temp-cleanup-guard.test.sh +133 -0
- package/tests/git-rm-orphan-wipe-guard.test.sh +66 -0
- package/tests/git-submodule-guard.test.sh +50 -0
- package/tests/grep-pcre-portability.test.sh +155 -0
- package/tests/hook-registration-matches-input.test.sh +73 -0
- package/tests/hook-trigger-matches-envelope.test.sh +178 -0
- package/tests/install-does-not-claim-protection.test.sh +110 -0
- package/tests/install-example-standalone-tools.test.sh +139 -0
- package/tests/line-continuation-bypass.test.sh +114 -0
- package/tests/mcp-config-poisoning-audit.test.sh +106 -0
- package/tests/nested-background-agent-guard.test.sh +58 -0
- package/tests/no-unqualified-safety-claims.test.sh +114 -0
- package/tests/option-eating-grep-patterns.test.sh +130 -0
- package/tests/outdated-core-guards.test.sh +134 -0
- package/tests/outdated-report.test.sh +155 -0
- package/tests/output-secret-mask-warns.test.sh +73 -0
- package/tests/plugin-hooks-fail-open-under-sh.test.sh +165 -0
- package/tests/plugins-word-order.test.sh +126 -0
- package/tests/powershell-remove-item-guard.test.sh +85 -0
- package/tests/project-dir-naming.test.sh +103 -0
- package/tests/quoted-safe-targets-and-mentions.test.sh +190 -0
- package/tests/reroute-after-block-guard.test.sh +104 -0
- package/tests/secret-guard-documented-promises.test.sh +97 -0
- package/tests/session-plugin-pin-watch.test.sh +45 -0
- package/tests/settings-unreadable-refuses-to-write.test.sh +95 -0
- package/tests/shield-no-silent-adoption.test.py +110 -0
- package/tests/shield-no-silent-adoption.test.sh +46 -0
- package/tests/stop-transcript-write-health.test.sh +46 -0
- package/tests/system-dir-guard-root-erased.test.sh +66 -0
- package/tests/test-account-billing-log.sh +100 -0
- package/tests/test-account-routing-preflight.sh +77 -0
- package/tests/test-agent-sdk-credit-pool-monitor.sh +157 -0
- package/tests/test-agent-view-quota-warn.sh +184 -0
- package/tests/test-agents-md-edit-drift-warner.sh +176 -0
- package/tests/test-agents-md-loader.sh +204 -0
- package/tests/test-agents-md-sync-checker.sh +125 -0
- package/tests/test-ai-slop-punctuation-arrest.sh +280 -0
- package/tests/test-allowlist.sh +60 -0
- package/tests/test-always-allow-pattern-suggester.sh +147 -0
- package/tests/test-anthropic-base-url-guard.sh +88 -0
- package/tests/test-articulated-scope-capture.sh +139 -0
- package/tests/test-attachment-traversal-guard.sh +168 -0
- package/tests/test-aup-block-pattern-logger.sh +315 -0
- package/tests/test-aup-false-positive-helper.sh +188 -0
- package/tests/test-aup-large-tool-output-warner.sh +370 -0
- package/tests/test-aup-retry-loop-guard.sh +341 -0
- package/tests/test-auth-expiry-reminder.sh +303 -0
- package/tests/test-auth-macos-sleep-detector.sh +254 -0
- package/tests/test-auth-path-detector.sh +232 -0
- package/tests/test-auth-status-checker.sh +233 -0
- package/tests/test-authorized-reconfirmation-detector.sh +280 -0
- package/tests/test-background-cost-launch-guard.sh +62 -0
- package/tests/test-bash-allowlist-secondary-check.sh +143 -0
- package/tests/test-bash-fanout-bounded-rewriter.sh +186 -0
- package/tests/test-bash-project-fence.sh +127 -0
- package/tests/test-bg-permission-prompt-warner.sh +221 -0
- package/tests/test-binary-read-detector.sh +173 -0
- package/tests/test-broad-prefix-session-trap-warner.sh +167 -0
- package/tests/test-bulk-delete-target-resolution.sh +49 -0
- package/tests/test-bypass-mode-effective-verifier.sh +179 -0
- package/tests/test-cache-creation-drift-detector.sh +244 -0
- package/tests/test-cache-residue-detector.sh +429 -0
- package/tests/test-cache-tier-logger.sh +59 -0
- package/tests/test-cache-ttl-eviction-detector.sh +282 -0
- package/tests/test-cch-sentinel-precommit-guard.sh +64 -0
- package/tests/test-claim-verify-detector.sh +222 -0
- package/tests/test-claim-vs-caveat-checker.sh +134 -0
- package/tests/test-claude-code-version-pin-advisor.sh +353 -0
- package/tests/test-claude-md-reinjector.sh +173 -0
- package/tests/test-claude-md-size-monitor.sh +107 -0
- package/tests/test-claude-update-budget-guard.sh +132 -0
- package/tests/test-claude-update-smart.sh +91 -0
- package/tests/test-claudemd-tool-prohibition.sh +239 -0
- package/tests/test-cli-config-pinning-detector.sh +233 -0
- package/tests/test-cliff-countdown-advisor.sh +138 -0
- package/tests/test-closure-word-verify-gate.sh +158 -0
- package/tests/test-commit-all-scope-guard.sh +73 -0
- package/tests/test-commitment-carry-forward-arrest.sh +250 -0
- package/tests/test-compact-dispatch-watchdog.sh +147 -0
- package/tests/test-completion-claim-without-verification-detector.sh +326 -0
- package/tests/test-compound-bash-permission-resolver.sh +264 -0
- package/tests/test-compound-command-deny-enforcer.sh +67 -0
- package/tests/test-context-length-budget.sh +68 -0
- package/tests/test-context-usage-drift-alert.sh +52 -22
- package/tests/test-cost-incident-self-audit.sh +94 -0
- package/tests/test-cowork-claude-md-load-checker.sh +257 -0
- package/tests/test-cowork-claudemd-helper.sh +141 -0
- package/tests/test-cowork-fuse-staleness-watcher.sh +287 -0
- package/tests/test-cowork-hook-absence-warner.sh +230 -0
- package/tests/test-cowork-model-picker-advisor.sh +317 -0
- package/tests/test-credential-exfil-guard.sh +62 -0
- package/tests/test-cron-create-receipt.sh +165 -0
- package/tests/test-cross-product-mcp-spawn-detector.sh +112 -0
- package/tests/test-daemon-zombie-worker-surfacer.sh +71 -0
- package/tests/test-daily-cost-guard.sh +131 -0
- package/tests/test-deny-rule-integrity-verifier.sh +288 -0
- package/tests/test-deployment-readback-gate.sh +92 -0
- package/tests/test-deployment-readback-gh-adapter.sh +163 -0
- package/tests/test-disabled-feature-toggle-advisor.sh +78 -0
- package/tests/test-dispatch-allowlist-preflight.sh +385 -0
- package/tests/test-dispatch-liveness-watchdog.sh +319 -0
- package/tests/test-dispatch-receipt.sh +314 -0
- package/tests/test-dotenv-anthropic-key-billing-guard.sh +160 -0
- package/tests/test-echo-probe-spam-detector.sh +143 -0
- package/tests/test-edit-quote-ambiguity-guard.sh +75 -0
- package/tests/test-ephemeral-container-detector.sh +251 -0
- package/tests/test-evidence-claim-gate.sh +291 -0
- package/tests/test-extended-thinking-loop-guard.sh +289 -0
- package/tests/test-extended-thinking-resume-warning.sh +240 -0
- package/tests/test-extended-thinking-tool-use-mismatch-detector.sh +236 -0
- package/tests/test-fabricated-command-detector.sh +296 -0
- package/tests/test-false-disk-full-guard.sh +36 -0
- package/tests/test-feature-deprecation-detector.sh +117 -0
- package/tests/test-forbidden-response-phrase-detector.sh +246 -0
- package/tests/test-git-operations-require-approval.sh +53 -0
- package/tests/test-git-push-blast-radius-guard.sh +115 -0
- package/tests/test-goal-iteration-limit-warner.sh +128 -0
- package/tests/test-growthbook-flag-monitor.sh +428 -0
- package/tests/test-halt-signal-detector.sh +120 -0
- package/tests/test-hook-self-disable-detector.sh +232 -0
- package/tests/test-iteration-quality-degradation-detector.sh +244 -0
- package/tests/test-long-session-malformed-tool-call-detector.sh +185 -0
- package/tests/test-marketplace-plugins.sh +193 -0
- package/tests/test-mcp-misdiagnosis-arrest.sh +235 -0
- package/tests/test-mcp-orphan-leak-warner.sh +71 -0
- package/tests/test-mcp-permissions-ask-warner.sh +207 -0
- package/tests/test-mcp-routine-approval-detector.sh +229 -0
- package/tests/test-mcp-startup-bloat-detector.sh +141 -0
- package/tests/test-mcp-stdio-compatibility-test.sh +112 -0
- package/tests/test-memory-chain-audit.sh +59 -0
- package/tests/test-memory-orphan-detector.sh +227 -0
- package/tests/test-model-swap-suggester.sh +368 -0
- package/tests/test-model-version-lock.sh +83 -0
- package/tests/test-multi-file-plan-routing-gate.sh +277 -0
- package/tests/test-multi-window-auth-drift-detector.sh +262 -0
- package/tests/test-nested-spawn-inflight-guard.sh +281 -0
- package/tests/test-no-force-flag.sh +49 -0
- package/tests/test-non-english-quality-warner.sh +229 -0
- package/tests/test-oauth-refresh-monitor.sh +311 -0
- package/tests/test-opus-degradation-tracker.sh +274 -0
- package/tests/test-opus48-routine-task-warning.sh +201 -0
- package/tests/test-opus48-thinking-wedge-advisor.sh +249 -0
- package/tests/test-output-token-spike-detector.sh +315 -0
- package/tests/test-parallel-batch-size-limiter.sh +228 -0
- package/tests/test-parallel-cascade-detector.sh +191 -0
- package/tests/test-partial-view-claim-arrest.sh +272 -0
- package/tests/test-per-prompt-token-cap.sh +136 -0
- package/tests/test-persisted-1m-model-advisor.sh +71 -0
- package/tests/test-plugin-hooks-json-bloat-detector.sh +267 -0
- package/tests/test-post-edit-disk-verify.sh +294 -0
- package/tests/test-pre-bash-sed-line-ending-windows.sh +108 -0
- package/tests/test-pre-execution-claim-detector.sh +366 -0
- package/tests/test-private-key-backup-and-git-credentials.sh +100 -0
- package/tests/test-proxy-capture-suggester.sh +214 -0
- package/tests/test-public-artefact-socratic-narrowing.sh +346 -0
- package/tests/test-quota-anomaly-detector.sh +321 -0
- package/tests/test-quota-reset-audit.sh +81 -0
- package/tests/test-read-loop-detector.sh +137 -0
- package/tests/test-read-once-guard.sh +85 -0
- package/tests/test-receipts-aggregate.sh +143 -0
- package/tests/test-redirect-fragment-warner.sh +130 -0
- package/tests/test-redundant-read-blocker.sh +155 -0
- package/tests/test-refusal-arrest-gate.sh +303 -0
- package/tests/test-remote-control-billing-classifier.sh +125 -0
- package/tests/test-resume-drift-watcher.sh +65 -0
- package/tests/test-rg-replace-flag-detector.sh +175 -0
- package/tests/test-rhetorical-verification-prompt-detector.sh +237 -0
- package/tests/test-rm-safety-net.sh +115 -0
- package/tests/test-route-handler-emptiness-gate.sh +300 -0
- package/tests/test-runtime-binary-change-detector.sh +196 -0
- package/tests/test-same-command-repeat-detector.sh +165 -0
- package/tests/test-same-correction-arrest.sh +165 -0
- package/tests/test-scope-expansion-receipt.sh +207 -0
- package/tests/test-server-side-prompt-injection-detector.sh +181 -0
- package/tests/test-session-persistence-verifier.sh +128 -0
- package/tests/test-session-rate-monitor.sh +284 -0
- package/tests/test-session-start-quota-status.sh +210 -0
- package/tests/test-session-start-safety-check.sh +138 -0
- package/tests/test-settings-hooks-key-restorer.sh +257 -0
- package/tests/test-settings-json-health-check.sh +70 -0
- package/tests/test-settings-regression-tester.sh +197 -0
- package/tests/test-skill-cumulative-size-detector.sh +198 -0
- package/tests/test-skill-description-drop-detector.sh +236 -0
- package/tests/test-skill-truncation-detector.sh +263 -0
- package/tests/test-skills-context-recorder.sh +329 -0
- package/tests/test-skills-load-verifier.sh +184 -0
- package/tests/test-skills-settings-validator.sh +242 -0
- package/tests/test-sonnet-45-deprecation-helper.sh +150 -0
- package/tests/test-spurious-malformed-notice-detector.sh +290 -0
- package/tests/test-sql-bulk-delete-warn.sh +123 -0
- package/tests/test-ssh-key-protect.sh +81 -0
- package/tests/test-stale-temp-settings-detector.sh +161 -0
- package/tests/test-standing-rule-session-surfacer.sh +215 -0
- package/tests/test-starter-hooks-manifest.sh +96 -0
- package/tests/test-stop-hook-sigterm-wrapper.sh +258 -0
- package/tests/test-strict-allowlist.sh +72 -0
- package/tests/test-subagent-boundary-precheck.sh +137 -0
- package/tests/test-subagent-closure-verify-gate.sh +193 -0
- package/tests/test-subagent-destructive-git-guard.sh +86 -0
- package/tests/test-subagent-identity-leak-guard.sh +62 -0
- package/tests/test-subagent-identity-reassertion.sh +61 -0
- package/tests/test-subagent-inheritance-tester.sh +319 -0
- package/tests/test-subagent-permission-mode-guard.sh +61 -0
- package/tests/test-subagent-spawn-verification-enforcer.sh +60 -0
- package/tests/test-subagent-tool-allowlist-enforcer.sh +62 -0
- package/tests/test-subagent-tool-call-limiter.sh +97 -0
- package/tests/test-subscription-api-billing-warner.sh +138 -0
- package/tests/test-subscription-bypass-detector.sh +255 -0
- package/tests/test-temporal-suggestion-detector.sh +183 -0
- package/tests/test-thinking-budget-effort-mismatch-detector.sh +327 -0
- package/tests/test-tokenizer-ratio-alert-corpus.sh +77 -0
- package/tests/test-tokenizer-ratio-alert.sh +93 -0
- package/tests/test-tool-result-correlation-checker.sh +264 -0
- package/tests/test-tool-result-size-guard.sh +121 -0
- package/tests/test-transcript-contamination-detector.sh +264 -0
- package/tests/test-trigger-header-parsing.sh +151 -0
- package/tests/test-ultrareview-large-diff-advisor.sh +192 -0
- package/tests/test-userprompt-submit-receipt.sh +181 -0
- package/tests/test-verify-after-publish-reminder.sh +184 -0
- package/tests/test-version-bump-detector.sh +212 -0
- package/tests/test-version-regression-warner.sh +165 -0
- package/tests/test-warn-cron-cost-trap.sh +82 -0
- package/tests/test-webfetch-runaway-guard.sh +77 -0
- package/tests/test-wellness-break-reminder.sh +138 -0
- package/tests/test-windows-destructive-command-guard.sh +169 -0
- package/tests/test-windows-python-stub-detector.sh +146 -0
- package/tests/test-worktree-edit-boundary-guard.sh +219 -0
- package/tests/test-write-byte-integrity-verifier.sh +192 -0
- package/tests/test-xml-format-leak-detector.sh +299 -0
- package/tests/trustfall-mcp-injection-guard.test.sh +183 -0
- package/tests/workspace-lease-guard.test.sh +144 -0
- package/tests/worktree-escape-write-guard.test.sh +68 -0
- package/tests/worktree-hooks-path-fix.test.sh +181 -0
- package/tests/worktree-parent-write-guard.test.sh +51 -0
- package/tests/write-empty-content-guard.test.sh +39 -0
- package/tests/write-nul-corruption-detector.test.sh +29 -0
- package/tests/write-overwrite-unread-content.test.sh +178 -0
- package/tests/wsl-host-disk-space-guard.test.sh +55 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Tests for subagent-destructive-git-guard.sh (Issue #57463 / #46444 / #53765 prevention)
|
|
3
|
+
HOOK="examples/subagent-destructive-git-guard.sh"
|
|
4
|
+
PASS=0 FAIL=0
|
|
5
|
+
|
|
6
|
+
assert_contains() { if echo "$2" | grep -q "$3"; then PASS=$((PASS+1)); else FAIL=$((FAIL+1)); echo "FAIL: $1 (expected '$3')"; fi; }
|
|
7
|
+
assert_not_contains() { if ! echo "$2" | grep -q "$3"; then PASS=$((PASS+1)); else FAIL=$((FAIL+1)); echo "FAIL: $1 (unexpected '$3')"; fi; }
|
|
8
|
+
assert_exit() { if [ "$2" = "$3" ]; then PASS=$((PASS+1)); else FAIL=$((FAIL+1)); echo "FAIL: $1 (expected exit $3, got $2)"; fi; }
|
|
9
|
+
|
|
10
|
+
# Test 1: Empty prompt should silently pass
|
|
11
|
+
OUT=$(echo '{"tool_input":{"prompt":""}}' | bash "$HOOK" 2>&1)
|
|
12
|
+
RC=$?
|
|
13
|
+
assert_not_contains "empty prompt no warning" "$OUT" "destructive-git boundary"
|
|
14
|
+
assert_exit "empty prompt exit 0" "$RC" "0"
|
|
15
|
+
|
|
16
|
+
# Test 2: Vague prompt should warn on all 3 checks
|
|
17
|
+
OUT=$(echo '{"tool_input":{"prompt":"please rename Tailwind classes across all .tsx files"}}' | bash "$HOOK" 2>&1)
|
|
18
|
+
RC=$?
|
|
19
|
+
assert_contains "vague warns destructive forbidden" "$OUT" "Destructive git commands not forbidden"
|
|
20
|
+
assert_contains "vague warns safe alternative" "$OUT" "No safe alternative named"
|
|
21
|
+
assert_contains "vague warns working tree check" "$OUT" "No working-tree state check"
|
|
22
|
+
assert_contains "vague references 57463" "$OUT" "#57463"
|
|
23
|
+
assert_contains "vague references 46444" "$OUT" "#46444"
|
|
24
|
+
assert_contains "vague references 53765" "$OUT" "#53765"
|
|
25
|
+
assert_exit "vague exit 0 advisory" "$RC" "0"
|
|
26
|
+
|
|
27
|
+
# Test 3: Destructive forbidden named, other 2 missing
|
|
28
|
+
OUT=$(echo '{"tool_input":{"prompt":"Do not use git checkout or git reset. Rename classes."}}' | bash "$HOOK" 2>&1)
|
|
29
|
+
assert_not_contains "destructive only no destructive warning" "$OUT" "Destructive git commands not forbidden"
|
|
30
|
+
assert_contains "destructive only warns alternative" "$OUT" "No safe alternative named"
|
|
31
|
+
assert_contains "destructive only warns tree check" "$OUT" "No working-tree state check"
|
|
32
|
+
|
|
33
|
+
# Test 4: Safe alternative named, other 2 missing
|
|
34
|
+
OUT=$(echo '{"tool_input":{"prompt":"Use git stash before any change. Rename classes."}}' | bash "$HOOK" 2>&1)
|
|
35
|
+
assert_contains "alternative only warns destructive" "$OUT" "Destructive git commands not forbidden"
|
|
36
|
+
assert_not_contains "alternative only no alternative warning" "$OUT" "No safe alternative named"
|
|
37
|
+
assert_contains "alternative only warns tree check" "$OUT" "No working-tree state check"
|
|
38
|
+
|
|
39
|
+
# Test 5: Working tree check named, other 2 missing
|
|
40
|
+
OUT=$(echo '{"tool_input":{"prompt":"Run git status first before any change. Rename classes."}}' | bash "$HOOK" 2>&1)
|
|
41
|
+
assert_contains "tree check only warns destructive" "$OUT" "Destructive git commands not forbidden"
|
|
42
|
+
assert_contains "tree check only warns alternative" "$OUT" "No safe alternative named"
|
|
43
|
+
assert_not_contains "tree check only no tree check warning" "$OUT" "No working-tree state check"
|
|
44
|
+
|
|
45
|
+
# Test 6: All 3 boundary instructions present, no warning
|
|
46
|
+
OUT=$(echo '{"tool_input":{"prompt":"Do not use git checkout, git reset, or git restore. Use git stash before any change. Run git status first to verify working tree state. Rename Tailwind classes across .tsx files."}}' | bash "$HOOK" 2>&1)
|
|
47
|
+
RC=$?
|
|
48
|
+
assert_not_contains "well-formed no warning" "$OUT" "destructive-git boundary"
|
|
49
|
+
assert_exit "well-formed exit 0" "$RC" "0"
|
|
50
|
+
|
|
51
|
+
# Test 7: Japanese prompt with all 3 instructions, no warning
|
|
52
|
+
OUT=$(echo '{"tool_input":{"prompt":"git checkout / git reset / git restore は禁止。stash の利用を優先。git status を最初に実行して作業の場の状態を確認してから、Tailwind class を rename する。"}}' | bash "$HOOK" 2>&1)
|
|
53
|
+
RC=$?
|
|
54
|
+
assert_not_contains "Japanese well-formed no warning" "$OUT" "destructive-git boundary"
|
|
55
|
+
assert_exit "Japanese well-formed exit 0" "$RC" "0"
|
|
56
|
+
|
|
57
|
+
# Test 8: Strict mode blocks vague prompts
|
|
58
|
+
OUT=$(echo '{"tool_input":{"prompt":"rename classes"}}' | CC_SUBAGENT_DESTRUCTIVE_GIT_REQUIRE_ALL=1 bash "$HOOK" 2>&1)
|
|
59
|
+
RC=$?
|
|
60
|
+
assert_contains "strict mode warns" "$OUT" "destructive-git boundary"
|
|
61
|
+
assert_exit "strict mode blocks (exit 2)" "$RC" "2"
|
|
62
|
+
|
|
63
|
+
# Test 9: Missing prompt field should silently pass
|
|
64
|
+
OUT=$(echo '{}' | bash "$HOOK" 2>&1)
|
|
65
|
+
RC=$?
|
|
66
|
+
assert_not_contains "missing prompt no warning" "$OUT" "destructive-git boundary"
|
|
67
|
+
assert_exit "missing prompt exit 0" "$RC" "0"
|
|
68
|
+
|
|
69
|
+
# Test 10: Strict mode passes when boundary is set
|
|
70
|
+
OUT=$(echo '{"tool_input":{"prompt":"Do not use git checkout. Use git stash. Check git status first. Rename."}}' | CC_SUBAGENT_DESTRUCTIVE_GIT_REQUIRE_ALL=1 bash "$HOOK" 2>&1)
|
|
71
|
+
RC=$?
|
|
72
|
+
assert_not_contains "strict well-formed no warning" "$OUT" "destructive-git boundary"
|
|
73
|
+
assert_exit "strict well-formed exit 0" "$RC" "0"
|
|
74
|
+
|
|
75
|
+
# Test 11: "destructive git" general phrase satisfies check 1
|
|
76
|
+
OUT=$(echo '{"tool_input":{"prompt":"No destructive git commands allowed. Use git stash. Check git status first."}}' | bash "$HOOK" 2>&1)
|
|
77
|
+
RC=$?
|
|
78
|
+
assert_not_contains "general phrase satisfies destructive check" "$OUT" "Destructive git commands not forbidden"
|
|
79
|
+
|
|
80
|
+
# Test 12: "ask the parent before" satisfies safe alternative check
|
|
81
|
+
OUT=$(echo '{"tool_input":{"prompt":"Do not use git checkout. Ask the parent before any destructive operation. Check git status first."}}' | bash "$HOOK" 2>&1)
|
|
82
|
+
RC=$?
|
|
83
|
+
assert_not_contains "ask parent satisfies alternative" "$OUT" "No safe alternative named"
|
|
84
|
+
|
|
85
|
+
echo "Results: $PASS passed, $FAIL failed"
|
|
86
|
+
[ "$FAIL" -eq 0 ]
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Tests for subagent-identity-leak-guard.sh (Issue #55488 prevention)
|
|
3
|
+
HOOK="examples/subagent-identity-leak-guard.sh"
|
|
4
|
+
PASS=0 FAIL=0
|
|
5
|
+
|
|
6
|
+
assert_contains() { if echo "$2" | grep -q "$3"; then PASS=$((PASS+1)); else FAIL=$((FAIL+1)); echo "FAIL: $1 (expected '$3')"; fi; }
|
|
7
|
+
assert_not_contains() { if ! echo "$2" | grep -q "$3"; then PASS=$((PASS+1)); else FAIL=$((FAIL+1)); echo "FAIL: $1 (unexpected '$3')"; fi; }
|
|
8
|
+
assert_exit() { if [ "$2" = "$3" ]; then PASS=$((PASS+1)); else FAIL=$((FAIL+1)); echo "FAIL: $1 (expected exit $3, got $2)"; fi; }
|
|
9
|
+
|
|
10
|
+
# Test 1: Empty prompt should silently pass
|
|
11
|
+
OUT=$(echo '{"tool_input":{"prompt":""}}' | bash "$HOOK" 2>&1)
|
|
12
|
+
RC=$?
|
|
13
|
+
assert_not_contains "empty prompt no warning" "$OUT" "Subagent identity boundary"
|
|
14
|
+
assert_exit "empty prompt exit 0" "$RC" "0"
|
|
15
|
+
|
|
16
|
+
# Test 2: Vague prompt should warn on all 3 checks
|
|
17
|
+
OUT=$(echo '{"tool_input":{"prompt":"please investigate the auth flow"}}' | bash "$HOOK" 2>&1)
|
|
18
|
+
RC=$?
|
|
19
|
+
assert_contains "vague prompt warns role" "$OUT" "No explicit role assignment"
|
|
20
|
+
assert_contains "vague prompt warns impersonation" "$OUT" "No prohibition against impersonating"
|
|
21
|
+
assert_contains "vague prompt warns history" "$OUT" "No prohibition against exposing"
|
|
22
|
+
assert_contains "vague prompt references issue" "$OUT" "#55488"
|
|
23
|
+
assert_exit "vague prompt exit 0 advisory" "$RC" "0"
|
|
24
|
+
|
|
25
|
+
# Test 3: Role assignment present, other 2 missing
|
|
26
|
+
OUT=$(echo '{"tool_input":{"prompt":"You are the backend agent. Investigate src/auth/login.ts."}}' | bash "$HOOK" 2>&1)
|
|
27
|
+
assert_not_contains "role only no role warning" "$OUT" "No explicit role"
|
|
28
|
+
assert_contains "role only warns impersonation" "$OUT" "No prohibition against impersonating"
|
|
29
|
+
assert_contains "role only warns history" "$OUT" "No prohibition against exposing"
|
|
30
|
+
|
|
31
|
+
# Test 4: Impersonation prohibition present, other 2 missing
|
|
32
|
+
OUT=$(echo '{"tool_input":{"prompt":"Do not identify as the parent. Do something useful."}}' | bash "$HOOK" 2>&1)
|
|
33
|
+
assert_contains "impersonation only warns role" "$OUT" "No explicit role"
|
|
34
|
+
assert_not_contains "impersonation only no impersonation warning" "$OUT" "No prohibition against impersonating"
|
|
35
|
+
assert_contains "impersonation only warns history" "$OUT" "No prohibition against exposing"
|
|
36
|
+
|
|
37
|
+
# Test 5: History prohibition present, other 2 missing
|
|
38
|
+
OUT=$(echo '{"tool_input":{"prompt":"Do not share the parent agent conversation history. Run a task."}}' | bash "$HOOK" 2>&1)
|
|
39
|
+
assert_contains "history only warns role" "$OUT" "No explicit role"
|
|
40
|
+
assert_contains "history only warns impersonation" "$OUT" "No prohibition against impersonating"
|
|
41
|
+
assert_not_contains "history only no history warning" "$OUT" "No prohibition against exposing"
|
|
42
|
+
|
|
43
|
+
# Test 6: All 3 boundary instructions present, no warning
|
|
44
|
+
OUT=$(echo '{"tool_input":{"prompt":"You are the backend agent. Do not identify as the parent or team-lead. Do not share the parent main agent conversation history. Investigate src/auth/login.ts."}}' | bash "$HOOK" 2>&1)
|
|
45
|
+
RC=$?
|
|
46
|
+
assert_not_contains "well-formed no warning" "$OUT" "Subagent identity boundary"
|
|
47
|
+
assert_exit "well-formed exit 0" "$RC" "0"
|
|
48
|
+
|
|
49
|
+
# Test 7: Strict mode (CC_SUBAGENT_IDENTITY_REQUIRE_ALL=1) blocks vague prompts
|
|
50
|
+
OUT=$(echo '{"tool_input":{"prompt":"investigate something"}}' | CC_SUBAGENT_IDENTITY_REQUIRE_ALL=1 bash "$HOOK" 2>&1)
|
|
51
|
+
RC=$?
|
|
52
|
+
assert_contains "strict mode warns" "$OUT" "Subagent identity boundary"
|
|
53
|
+
assert_exit "strict mode blocks (exit 2)" "$RC" "2"
|
|
54
|
+
|
|
55
|
+
# Test 8: Missing prompt field should silently pass
|
|
56
|
+
OUT=$(echo '{}' | bash "$HOOK" 2>&1)
|
|
57
|
+
RC=$?
|
|
58
|
+
assert_not_contains "missing prompt no warning" "$OUT" "Subagent identity boundary"
|
|
59
|
+
assert_exit "missing prompt exit 0" "$RC" "0"
|
|
60
|
+
|
|
61
|
+
echo "Results: $PASS passed, $FAIL failed"
|
|
62
|
+
[ "$FAIL" -eq 0 ]
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Tests for subagent-identity-reassertion.sh — Issue #55488 mitigation hook
|
|
3
|
+
HOOK="examples/subagent-identity-reassertion.sh"
|
|
4
|
+
PASS=0 FAIL=0
|
|
5
|
+
|
|
6
|
+
assert_contains() { if echo "$2" | grep -q "$3"; then PASS=$((PASS+1)); else FAIL=$((FAIL+1)); echo "FAIL: $1 (expected '$3')"; fi; }
|
|
7
|
+
assert_not_contains() { if ! echo "$2" | grep -q "$3"; then PASS=$((PASS+1)); else FAIL=$((FAIL+1)); echo "FAIL: $1 (unexpected '$3')"; fi; }
|
|
8
|
+
assert_exit_code() { if [ "$2" -eq "$3" ]; then PASS=$((PASS+1)); else FAIL=$((FAIL+1)); echo "FAIL: $1 (expected exit $3, got $2)"; fi; }
|
|
9
|
+
|
|
10
|
+
# Test 1: Agent tool with subagent_type emits reminder block
|
|
11
|
+
OUT=$(echo '{"tool_name":"Agent","tool_input":{"subagent_type":"general-purpose","name":"backend"}}' | bash "$HOOK" 2>&1)
|
|
12
|
+
RC=$?
|
|
13
|
+
assert_contains "Agent tool emits reminder header" "$OUT" "subagent-identity-reassertion"
|
|
14
|
+
assert_contains "reminder includes subagent label" "$OUT" "backend (general-purpose)"
|
|
15
|
+
assert_contains "reminder mentions Issue #55488" "$OUT" "#55488"
|
|
16
|
+
assert_contains "reminder includes parent-relay guard" "$OUT" "route sensitive DMs through the parent"
|
|
17
|
+
assert_contains "reminder includes context audit guard" "$OUT" "parent context does not contain secrets"
|
|
18
|
+
assert_contains "reminder includes identity-lock guard" "$OUT" "Confirm"
|
|
19
|
+
assert_exit_code "Agent tool exit 0" "$RC" 0
|
|
20
|
+
|
|
21
|
+
# Test 2: Bash tool skips silently with exit 0 (non-Agent fast path)
|
|
22
|
+
OUT=$(echo '{"tool_name":"Bash","tool_input":{"command":"ls"}}' | bash "$HOOK" 2>&1)
|
|
23
|
+
RC=$?
|
|
24
|
+
assert_not_contains "Bash tool emits no reminder" "$OUT" "subagent-identity-reassertion"
|
|
25
|
+
assert_exit_code "Bash tool exit 0" "$RC" 0
|
|
26
|
+
|
|
27
|
+
# Test 3: Empty tool_name skips silently
|
|
28
|
+
OUT=$(echo '{}' | bash "$HOOK" 2>&1)
|
|
29
|
+
RC=$?
|
|
30
|
+
assert_not_contains "empty input emits no reminder" "$OUT" "subagent-identity-reassertion"
|
|
31
|
+
assert_exit_code "empty input exit 0" "$RC" 0
|
|
32
|
+
|
|
33
|
+
# Test 4: Agent without subagent_type still emits reminder with default label
|
|
34
|
+
OUT=$(echo '{"tool_name":"Agent","tool_input":{}}' | bash "$HOOK" 2>&1)
|
|
35
|
+
RC=$?
|
|
36
|
+
assert_contains "Agent without subagent_type still warns" "$OUT" "subagent-identity-reassertion"
|
|
37
|
+
assert_contains "default role label is subagent" "$OUT" "Spawning subagent"
|
|
38
|
+
assert_exit_code "Agent without subagent_type exit 0" "$RC" 0
|
|
39
|
+
|
|
40
|
+
# Test 5: Agent with only subagent_type (no name)
|
|
41
|
+
OUT=$(echo '{"tool_name":"Agent","tool_input":{"subagent_type":"general-purpose"}}' | bash "$HOOK" 2>&1)
|
|
42
|
+
RC=$?
|
|
43
|
+
assert_contains "Agent with only subagent_type" "$OUT" "Spawning general-purpose"
|
|
44
|
+
assert_exit_code "exit 0" "$RC" 0
|
|
45
|
+
|
|
46
|
+
# Test 6: Read tool (another non-Agent) skips silently
|
|
47
|
+
OUT=$(echo '{"tool_name":"Read","tool_input":{"file_path":"/tmp/x"}}' | bash "$HOOK" 2>&1)
|
|
48
|
+
RC=$?
|
|
49
|
+
assert_not_contains "Read tool emits no reminder" "$OUT" "subagent-identity-reassertion"
|
|
50
|
+
assert_exit_code "Read tool exit 0" "$RC" 0
|
|
51
|
+
|
|
52
|
+
# Test 7: Malformed JSON falls through silently (jq returns empty)
|
|
53
|
+
OUT=$(echo 'not json' | bash "$HOOK" 2>&1)
|
|
54
|
+
RC=$?
|
|
55
|
+
assert_not_contains "malformed JSON does not warn" "$OUT" "subagent-identity-reassertion"
|
|
56
|
+
# Note: jq exits with non-zero on malformed JSON, but `// empty` + set -euo
|
|
57
|
+
# may cause exit 1 here. Accept exit 0 or 1 (silent failure is acceptable).
|
|
58
|
+
[ "$RC" -le 1 ] && PASS=$((PASS+1)) || { FAIL=$((FAIL+1)); echo "FAIL: malformed JSON exit code $RC > 1"; }
|
|
59
|
+
|
|
60
|
+
echo "Results: $PASS passed, $FAIL failed"
|
|
61
|
+
[ "$FAIL" -eq 0 ]
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Tests for subagent-inheritance-tester.sh — verifies that subagent
|
|
3
|
+
# frontmatter gaps (missing tools:, memory: misuse, missing name:,
|
|
4
|
+
# no frontmatter) are surfaced, and that parent Deny rules escalate
|
|
5
|
+
# the warning text for missing tool bindings.
|
|
6
|
+
|
|
7
|
+
HOOK="examples/subagent-inheritance-tester.sh"
|
|
8
|
+
PASS=0 FAIL=0
|
|
9
|
+
|
|
10
|
+
assert_contains() { if echo "$2" | grep -q "$3"; then PASS=$((PASS+1)); else FAIL=$((FAIL+1)); echo "FAIL: $1 (expected '$3' in: $2)"; fi; }
|
|
11
|
+
assert_not_contains() { if ! echo "$2" | grep -q "$3"; then PASS=$((PASS+1)); else FAIL=$((FAIL+1)); echo "FAIL: $1 (unexpected '$3' in: $2)"; fi; }
|
|
12
|
+
assert_exit() { if [ "$2" -eq "$3" ]; then PASS=$((PASS+1)); else FAIL=$((FAIL+1)); echo "FAIL: $1 (exit $2, expected $3)"; fi; }
|
|
13
|
+
|
|
14
|
+
TMPDIR=$(mktemp -d)
|
|
15
|
+
PROJ_DIR="$TMPDIR/project"
|
|
16
|
+
HOME_AGENTS="$TMPDIR/home/.claude/agents"
|
|
17
|
+
PROJ_AGENTS="$PROJ_DIR/.claude/agents"
|
|
18
|
+
mkdir -p "$HOME_AGENTS" "$PROJ_AGENTS"
|
|
19
|
+
|
|
20
|
+
# Run the hook with isolated $HOME and a synthetic project cwd.
|
|
21
|
+
run_hook() {
|
|
22
|
+
local cwd="$1"
|
|
23
|
+
local input
|
|
24
|
+
input=$(jq -n --arg c "$cwd" '{cwd: $c}')
|
|
25
|
+
printf '%s' "$input" | HOME="$TMPDIR/home" bash "$HOOK" 2>&1
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
# ---- Test 1: empty input + no agents → exit 0 silently ----
|
|
29
|
+
rm -rf "$TMPDIR/home/.claude/agents"
|
|
30
|
+
OUT=$(echo '{}' | HOME="$TMPDIR/home" bash "$HOOK" 2>&1)
|
|
31
|
+
RC=$?
|
|
32
|
+
assert_exit "no agents dir exits 0" "$RC" 0
|
|
33
|
+
assert_not_contains "no agents dir no output" "$OUT" "subagent-inheritance"
|
|
34
|
+
mkdir -p "$HOME_AGENTS"
|
|
35
|
+
|
|
36
|
+
# ---- Test 2: well-formed agent with tools: → no warning ----
|
|
37
|
+
cat > "$HOME_AGENTS/good.md" <<'EOF'
|
|
38
|
+
---
|
|
39
|
+
name: good-agent
|
|
40
|
+
description: Tightly scoped helper
|
|
41
|
+
tools: Read, Grep
|
|
42
|
+
model: sonnet
|
|
43
|
+
---
|
|
44
|
+
You are a focused helper.
|
|
45
|
+
EOF
|
|
46
|
+
OUT=$(run_hook "$PROJ_DIR")
|
|
47
|
+
RC=$?
|
|
48
|
+
assert_exit "well-formed agent exits 0" "$RC" 0
|
|
49
|
+
assert_not_contains "well-formed agent no warning" "$OUT" "subagent-inheritance"
|
|
50
|
+
|
|
51
|
+
# ---- Test 3: agent without frontmatter → warning ----
|
|
52
|
+
cat > "$HOME_AGENTS/no-frontmatter.md" <<'EOF'
|
|
53
|
+
You are an agent without YAML frontmatter.
|
|
54
|
+
EOF
|
|
55
|
+
OUT=$(run_hook "$PROJ_DIR")
|
|
56
|
+
RC=$?
|
|
57
|
+
assert_exit "no-frontmatter exits 0 (warn-only)" "$RC" 0
|
|
58
|
+
assert_contains "no-frontmatter warned" "$OUT" "no YAML frontmatter"
|
|
59
|
+
|
|
60
|
+
# ---- Test 4: agent missing tools: → warning ----
|
|
61
|
+
rm -f "$HOME_AGENTS/no-frontmatter.md"
|
|
62
|
+
cat > "$HOME_AGENTS/missing-tools.md" <<'EOF'
|
|
63
|
+
---
|
|
64
|
+
name: missing-tools
|
|
65
|
+
description: Agent with no explicit tools list
|
|
66
|
+
model: sonnet
|
|
67
|
+
---
|
|
68
|
+
Body.
|
|
69
|
+
EOF
|
|
70
|
+
OUT=$(run_hook "$PROJ_DIR")
|
|
71
|
+
RC=$?
|
|
72
|
+
assert_exit "missing-tools exits 0" "$RC" 0
|
|
73
|
+
assert_contains "missing-tools warned about default tool set" "$OUT" "no explicit 'tools:' list"
|
|
74
|
+
|
|
75
|
+
# ---- Test 5: agent with memory: field → warned about #57507 ----
|
|
76
|
+
cat > "$HOME_AGENTS/memory-only.md" <<'EOF'
|
|
77
|
+
---
|
|
78
|
+
name: memory-only
|
|
79
|
+
description: Author thought memory: would scope this agent
|
|
80
|
+
memory: scoped
|
|
81
|
+
tools: Read
|
|
82
|
+
---
|
|
83
|
+
Body.
|
|
84
|
+
EOF
|
|
85
|
+
OUT=$(run_hook "$PROJ_DIR")
|
|
86
|
+
RC=$?
|
|
87
|
+
assert_exit "memory-only exits 0" "$RC" 0
|
|
88
|
+
assert_contains "memory-only flagged" "$OUT" "57507"
|
|
89
|
+
assert_contains "memory-only mentions silently ignored" "$OUT" "silently ignored"
|
|
90
|
+
rm -f "$HOME_AGENTS/memory-only.md"
|
|
91
|
+
|
|
92
|
+
# ---- Test 6: agent missing name: → warning ----
|
|
93
|
+
cat > "$HOME_AGENTS/no-name.md" <<'EOF'
|
|
94
|
+
---
|
|
95
|
+
description: Missing required name key
|
|
96
|
+
tools: Read
|
|
97
|
+
---
|
|
98
|
+
Body.
|
|
99
|
+
EOF
|
|
100
|
+
OUT=$(run_hook "$PROJ_DIR")
|
|
101
|
+
RC=$?
|
|
102
|
+
assert_exit "no-name exits 0" "$RC" 0
|
|
103
|
+
assert_contains "no-name warned" "$OUT" "missing required 'name:'"
|
|
104
|
+
rm -f "$HOME_AGENTS/no-name.md"
|
|
105
|
+
|
|
106
|
+
# ---- Test 7: parent Deny rules escalate missing-tools warning ----
|
|
107
|
+
mkdir -p "$TMPDIR/home/.claude"
|
|
108
|
+
cat > "$TMPDIR/home/.claude/settings.json" <<'EOF'
|
|
109
|
+
{
|
|
110
|
+
"permissions": {
|
|
111
|
+
"deny": ["Read(./.env)", "Read(./.env.*)"]
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
EOF
|
|
115
|
+
OUT=$(run_hook "$PROJ_DIR")
|
|
116
|
+
RC=$?
|
|
117
|
+
assert_exit "deny-rules + missing tools exits 0" "$RC" 0
|
|
118
|
+
assert_contains "deny-rules escalation cites #57068" "$OUT" "57068"
|
|
119
|
+
assert_contains "deny-rules listed in output" "$OUT" "Read(./.env)"
|
|
120
|
+
|
|
121
|
+
# ---- Test 8: BLOCK=1 with issues → exit 2 ----
|
|
122
|
+
OUT=$(CC_SUBAGENT_INHERITANCE_BLOCK=1 run_hook "$PROJ_DIR")
|
|
123
|
+
RC=$?
|
|
124
|
+
assert_exit "block mode with issues exits 2" "$RC" 2
|
|
125
|
+
assert_contains "block mode still emits warning text" "$OUT" "subagent-inheritance"
|
|
126
|
+
|
|
127
|
+
# ---- Test 9: BLOCK=1 with no issues → exit 0 ----
|
|
128
|
+
rm -f "$HOME_AGENTS/missing-tools.md"
|
|
129
|
+
OUT=$(CC_SUBAGENT_INHERITANCE_BLOCK=1 run_hook "$PROJ_DIR")
|
|
130
|
+
RC=$?
|
|
131
|
+
assert_exit "block mode without issues exits 0" "$RC" 0
|
|
132
|
+
assert_not_contains "block mode no issues no warning" "$OUT" "subagent-inheritance"
|
|
133
|
+
|
|
134
|
+
# ---- Test 10: project-level .claude/agents/ scanned via cwd ----
|
|
135
|
+
cat > "$PROJ_AGENTS/proj-agent.md" <<'EOF'
|
|
136
|
+
---
|
|
137
|
+
name: proj-agent
|
|
138
|
+
description: Project agent with no tools
|
|
139
|
+
---
|
|
140
|
+
Body.
|
|
141
|
+
EOF
|
|
142
|
+
OUT=$(run_hook "$PROJ_DIR")
|
|
143
|
+
RC=$?
|
|
144
|
+
assert_exit "project agent dir exits 0" "$RC" 0
|
|
145
|
+
assert_contains "project agent dir scanned" "$OUT" "proj-agent.md"
|
|
146
|
+
rm -f "$PROJ_AGENTS/proj-agent.md"
|
|
147
|
+
|
|
148
|
+
# ---- Test 11: backup files (.bak) skipped ----
|
|
149
|
+
cat > "$HOME_AGENTS/old.md.bak" <<'EOF'
|
|
150
|
+
broken file
|
|
151
|
+
EOF
|
|
152
|
+
OUT=$(run_hook "$PROJ_DIR")
|
|
153
|
+
RC=$?
|
|
154
|
+
assert_exit "backup file skipped exits 0" "$RC" 0
|
|
155
|
+
assert_not_contains "backup file not warned" "$OUT" "old.md.bak"
|
|
156
|
+
rm -f "$HOME_AGENTS/old.md.bak"
|
|
157
|
+
|
|
158
|
+
# ---- Test 12: extra paths via env var ----
|
|
159
|
+
mkdir -p "$TMPDIR/extra"
|
|
160
|
+
cat > "$TMPDIR/extra/extra-agent.md" <<'EOF'
|
|
161
|
+
---
|
|
162
|
+
description: extra path agent missing name and tools
|
|
163
|
+
---
|
|
164
|
+
Body.
|
|
165
|
+
EOF
|
|
166
|
+
OUT=$(CC_SUBAGENT_INHERITANCE_PATHS="$TMPDIR/extra" run_hook "$PROJ_DIR")
|
|
167
|
+
RC=$?
|
|
168
|
+
assert_exit "extra path agent exits 0" "$RC" 0
|
|
169
|
+
assert_contains "extra path agent scanned" "$OUT" "extra-agent.md"
|
|
170
|
+
|
|
171
|
+
# ---- Test 13: real-world #57068 repro — Deny .env + agent w/o tools ----
|
|
172
|
+
cat > "$HOME_AGENTS/57068-repro.md" <<'EOF'
|
|
173
|
+
---
|
|
174
|
+
name: helpful
|
|
175
|
+
description: General helper
|
|
176
|
+
---
|
|
177
|
+
You may help with anything.
|
|
178
|
+
EOF
|
|
179
|
+
OUT=$(run_hook "$PROJ_DIR")
|
|
180
|
+
RC=$?
|
|
181
|
+
assert_exit "#57068 repro exits 0" "$RC" 0
|
|
182
|
+
assert_contains "#57068 repro escalates with deny" "$OUT" "57068"
|
|
183
|
+
assert_contains "#57068 repro names the file" "$OUT" "57068-repro.md"
|
|
184
|
+
rm -f "$HOME_AGENTS/57068-repro.md"
|
|
185
|
+
|
|
186
|
+
# ---- Test 14: real-world #57507 repro — memory: present ----
|
|
187
|
+
cat > "$HOME_AGENTS/57507-repro.md" <<'EOF'
|
|
188
|
+
---
|
|
189
|
+
name: scoped
|
|
190
|
+
description: Author tried to bind via memory:
|
|
191
|
+
memory:
|
|
192
|
+
scope: subagent-only
|
|
193
|
+
tools: Read
|
|
194
|
+
---
|
|
195
|
+
Body.
|
|
196
|
+
EOF
|
|
197
|
+
OUT=$(run_hook "$PROJ_DIR")
|
|
198
|
+
RC=$?
|
|
199
|
+
assert_exit "#57507 repro exits 0" "$RC" 0
|
|
200
|
+
assert_contains "#57507 repro flags memory:" "$OUT" "57507"
|
|
201
|
+
rm -f "$HOME_AGENTS/57507-repro.md"
|
|
202
|
+
|
|
203
|
+
# ---- Test 15: empty frontmatter block ----
|
|
204
|
+
printf -- '---\n---\nbody only\n' > "$HOME_AGENTS/empty-fm.md"
|
|
205
|
+
OUT=$(run_hook "$PROJ_DIR")
|
|
206
|
+
RC=$?
|
|
207
|
+
assert_exit "empty frontmatter exits 0" "$RC" 0
|
|
208
|
+
assert_contains "empty frontmatter warned" "$OUT" "empty-fm.md"
|
|
209
|
+
rm -f "$HOME_AGENTS/empty-fm.md"
|
|
210
|
+
|
|
211
|
+
# ---- Test 16: settings without deny → no escalation text ----
|
|
212
|
+
cat > "$TMPDIR/home/.claude/settings.json" <<'EOF'
|
|
213
|
+
{}
|
|
214
|
+
EOF
|
|
215
|
+
cat > "$HOME_AGENTS/missing-tools-2.md" <<'EOF'
|
|
216
|
+
---
|
|
217
|
+
name: ok-name
|
|
218
|
+
description: missing tools
|
|
219
|
+
---
|
|
220
|
+
Body.
|
|
221
|
+
EOF
|
|
222
|
+
OUT=$(run_hook "$PROJ_DIR")
|
|
223
|
+
RC=$?
|
|
224
|
+
assert_exit "no-deny + missing tools exits 0" "$RC" 0
|
|
225
|
+
assert_contains "no-deny still warns about default tool set" "$OUT" "Pin to least-privilege"
|
|
226
|
+
# Per-line warning should not escalate (no #57068 inline). Reference list
|
|
227
|
+
# at the bottom always cites both issues, so check only the issue line.
|
|
228
|
+
ISSUE_LINE=$(echo "$OUT" | grep "missing-tools-2.md" || true)
|
|
229
|
+
assert_not_contains "no-deny issue line does not cite #57068" "$ISSUE_LINE" "57068"
|
|
230
|
+
rm -f "$HOME_AGENTS/missing-tools-2.md"
|
|
231
|
+
|
|
232
|
+
# ---- Test 17: malformed JSON input → still scans HOME via $CLAUDE_PROJECT_DIR fallback ----
|
|
233
|
+
cat > "$HOME_AGENTS/needs-tools.md" <<'EOF'
|
|
234
|
+
---
|
|
235
|
+
name: needs-tools
|
|
236
|
+
description: missing tools
|
|
237
|
+
---
|
|
238
|
+
Body.
|
|
239
|
+
EOF
|
|
240
|
+
OUT=$(printf 'not-json' | HOME="$TMPDIR/home" bash "$HOOK" 2>&1)
|
|
241
|
+
RC=$?
|
|
242
|
+
assert_exit "non-json input exits 0" "$RC" 0
|
|
243
|
+
assert_contains "non-json input still scans home agents" "$OUT" "needs-tools.md"
|
|
244
|
+
|
|
245
|
+
# ---- Test 18: well-formed + tools list → no warning even with deny ----
|
|
246
|
+
rm -f "$HOME_AGENTS/needs-tools.md"
|
|
247
|
+
cat > "$TMPDIR/home/.claude/settings.json" <<'EOF'
|
|
248
|
+
{
|
|
249
|
+
"permissions": {
|
|
250
|
+
"deny": ["Read(./.env)"]
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
EOF
|
|
254
|
+
cat > "$HOME_AGENTS/scoped.md" <<'EOF'
|
|
255
|
+
---
|
|
256
|
+
name: scoped
|
|
257
|
+
description: properly scoped
|
|
258
|
+
tools: Read, Grep, Bash
|
|
259
|
+
---
|
|
260
|
+
Body.
|
|
261
|
+
EOF
|
|
262
|
+
OUT=$(run_hook "$PROJ_DIR")
|
|
263
|
+
RC=$?
|
|
264
|
+
assert_exit "scoped+deny exits 0" "$RC" 0
|
|
265
|
+
assert_not_contains "scoped+deny no warning" "$OUT" "subagent-inheritance"
|
|
266
|
+
rm -f "$HOME_AGENTS/scoped.md"
|
|
267
|
+
rm -f "$TMPDIR/home/.claude/settings.json"
|
|
268
|
+
|
|
269
|
+
# ---- Test 19: many agents, mixed states → each issue named ----
|
|
270
|
+
cat > "$HOME_AGENTS/good-1.md" <<'EOF'
|
|
271
|
+
---
|
|
272
|
+
name: g1
|
|
273
|
+
tools: Read
|
|
274
|
+
---
|
|
275
|
+
Body.
|
|
276
|
+
EOF
|
|
277
|
+
cat > "$HOME_AGENTS/bad-1.md" <<'EOF'
|
|
278
|
+
---
|
|
279
|
+
name: b1
|
|
280
|
+
description: missing tools
|
|
281
|
+
---
|
|
282
|
+
Body.
|
|
283
|
+
EOF
|
|
284
|
+
cat > "$HOME_AGENTS/bad-2.md" <<'EOF'
|
|
285
|
+
---
|
|
286
|
+
name: b2
|
|
287
|
+
memory: legacy
|
|
288
|
+
tools: Read
|
|
289
|
+
---
|
|
290
|
+
Body.
|
|
291
|
+
EOF
|
|
292
|
+
OUT=$(run_hook "$PROJ_DIR")
|
|
293
|
+
RC=$?
|
|
294
|
+
assert_exit "mixed agents exits 0" "$RC" 0
|
|
295
|
+
assert_contains "mixed agents flag bad-1" "$OUT" "bad-1.md"
|
|
296
|
+
assert_contains "mixed agents flag bad-2" "$OUT" "bad-2.md"
|
|
297
|
+
assert_not_contains "mixed agents skip good-1" "$OUT" "good-1.md"
|
|
298
|
+
rm -f "$HOME_AGENTS/good-1.md" "$HOME_AGENTS/bad-1.md" "$HOME_AGENTS/bad-2.md"
|
|
299
|
+
|
|
300
|
+
# ---- Test 20: Japanese description with English frontmatter keys ----
|
|
301
|
+
cat > "$HOME_AGENTS/jp.md" <<'EOF'
|
|
302
|
+
---
|
|
303
|
+
name: jp-agent
|
|
304
|
+
description: 日本語の説明 — tools 列が無い
|
|
305
|
+
---
|
|
306
|
+
本文
|
|
307
|
+
EOF
|
|
308
|
+
OUT=$(run_hook "$PROJ_DIR")
|
|
309
|
+
RC=$?
|
|
310
|
+
assert_exit "jp agent exits 0" "$RC" 0
|
|
311
|
+
assert_contains "jp agent flagged" "$OUT" "jp.md"
|
|
312
|
+
|
|
313
|
+
# Cleanup
|
|
314
|
+
rm -rf "$TMPDIR"
|
|
315
|
+
|
|
316
|
+
echo ""
|
|
317
|
+
echo "PASS: $PASS"
|
|
318
|
+
echo "FAIL: $FAIL"
|
|
319
|
+
[ "$FAIL" -eq 0 ] && echo "OK" || exit 1
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Tests for subagent-permission-mode-guard.sh (Issue #55691 prevention)
|
|
3
|
+
HOOK="examples/subagent-permission-mode-guard.sh"
|
|
4
|
+
PASS=0 FAIL=0
|
|
5
|
+
|
|
6
|
+
assert_contains() { if echo "$2" | grep -q "$3"; then PASS=$((PASS+1)); else FAIL=$((FAIL+1)); echo "FAIL: $1 (expected '$3')"; fi; }
|
|
7
|
+
assert_not_contains() { if ! echo "$2" | grep -q "$3"; then PASS=$((PASS+1)); else FAIL=$((FAIL+1)); echo "FAIL: $1 (unexpected '$3')"; fi; }
|
|
8
|
+
assert_exit() { if [ "$2" = "$3" ]; then PASS=$((PASS+1)); else FAIL=$((FAIL+1)); echo "FAIL: $1 (expected exit $3, got $2)"; fi; }
|
|
9
|
+
|
|
10
|
+
# Test 1: No mode parameter, silent pass
|
|
11
|
+
OUT=$(echo '{"tool_input":{"prompt":"do something"}}' | bash "$HOOK" 2>&1)
|
|
12
|
+
RC=$?
|
|
13
|
+
assert_not_contains "no mode no warning" "$OUT" "Subagent permission mode"
|
|
14
|
+
assert_not_contains "no mode no early warn" "$OUT" "may be silently overridden"
|
|
15
|
+
assert_exit "no mode exit 0" "$RC" "0"
|
|
16
|
+
|
|
17
|
+
# Test 2: Mode parameter with no prompt
|
|
18
|
+
OUT=$(echo '{"tool_input":{"mode":"bypassPermissions","prompt":""}}' | bash "$HOOK" 2>&1)
|
|
19
|
+
RC=$?
|
|
20
|
+
assert_contains "empty prompt with mode warns" "$OUT" "may be silently overridden"
|
|
21
|
+
assert_contains "empty prompt with mode references issue" "$OUT" "#55691"
|
|
22
|
+
assert_exit "empty prompt with mode exit 0" "$RC" "0"
|
|
23
|
+
|
|
24
|
+
# Test 3: Mode parameter with vague prompt warns 2 items
|
|
25
|
+
OUT=$(echo '{"tool_input":{"mode":"bypassPermissions","prompt":"please investigate the auth flow"}}' | bash "$HOOK" 2>&1)
|
|
26
|
+
RC=$?
|
|
27
|
+
assert_contains "vague warns frontmatter" "$OUT" "frontmatter override risk"
|
|
28
|
+
assert_contains "vague warns verification" "$OUT" "verification of the actual effective mode"
|
|
29
|
+
assert_contains "vague references issue" "$OUT" "#55691"
|
|
30
|
+
assert_exit "vague exit 0 advisory" "$RC" "0"
|
|
31
|
+
|
|
32
|
+
# Test 4: Frontmatter mention only
|
|
33
|
+
OUT=$(echo '{"tool_input":{"mode":"bypassPermissions","prompt":"check if the frontmatter has permissionMode and run."}}' | bash "$HOOK" 2>&1)
|
|
34
|
+
assert_not_contains "frontmatter only no frontmatter warning" "$OUT" "frontmatter override risk"
|
|
35
|
+
assert_contains "frontmatter only warns verification" "$OUT" "verification of the actual"
|
|
36
|
+
|
|
37
|
+
# Test 5: Verification mention only
|
|
38
|
+
OUT=$(echo '{"tool_input":{"mode":"bypassPermissions","prompt":"run the task and verify the mode is active."}}' | bash "$HOOK" 2>&1)
|
|
39
|
+
assert_contains "verify only warns frontmatter" "$OUT" "frontmatter override risk"
|
|
40
|
+
assert_not_contains "verify only no verify warning" "$OUT" "verification of the actual"
|
|
41
|
+
|
|
42
|
+
# Test 6: All instructions present, no warning
|
|
43
|
+
OUT=$(echo '{"tool_input":{"mode":"bypassPermissions","prompt":"check if the frontmatter has permissionMode set, then run the task and verify the effective permission is bypassPermissions."}}' | bash "$HOOK" 2>&1)
|
|
44
|
+
RC=$?
|
|
45
|
+
assert_not_contains "well-formed no warning" "$OUT" "Subagent permission mode boundary"
|
|
46
|
+
assert_exit "well-formed exit 0" "$RC" "0"
|
|
47
|
+
|
|
48
|
+
# Test 7: Strict mode blocks vague
|
|
49
|
+
OUT=$(echo '{"tool_input":{"mode":"bypassPermissions","prompt":"investigate something"}}' | CC_SUBAGENT_MODE_REQUIRE_ALL=1 bash "$HOOK" 2>&1)
|
|
50
|
+
RC=$?
|
|
51
|
+
assert_contains "strict mode warns" "$OUT" "Subagent permission mode boundary"
|
|
52
|
+
assert_exit "strict mode blocks (exit 2)" "$RC" "2"
|
|
53
|
+
|
|
54
|
+
# Test 8: Empty input, no mode
|
|
55
|
+
OUT=$(echo '{}' | bash "$HOOK" 2>&1)
|
|
56
|
+
RC=$?
|
|
57
|
+
assert_not_contains "empty input no warning" "$OUT" "Subagent permission mode"
|
|
58
|
+
assert_exit "empty input exit 0" "$RC" "0"
|
|
59
|
+
|
|
60
|
+
echo "Results: $PASS passed, $FAIL failed"
|
|
61
|
+
[ "$FAIL" -eq 0 ]
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Tests for subagent-spawn-verification-enforcer.sh (Issue #55666 prevention)
|
|
3
|
+
HOOK="examples/subagent-spawn-verification-enforcer.sh"
|
|
4
|
+
PASS=0 FAIL=0
|
|
5
|
+
|
|
6
|
+
assert_contains() { if echo "$2" | grep -q "$3"; then PASS=$((PASS+1)); else FAIL=$((FAIL+1)); echo "FAIL: $1 (expected '$3')"; fi; }
|
|
7
|
+
assert_not_contains() { if ! echo "$2" | grep -q "$3"; then PASS=$((PASS+1)); else FAIL=$((FAIL+1)); echo "FAIL: $1 (unexpected '$3')"; fi; }
|
|
8
|
+
assert_exit() { if [ "$2" = "$3" ]; then PASS=$((PASS+1)); else FAIL=$((FAIL+1)); echo "FAIL: $1 (expected exit $3, got $2)"; fi; }
|
|
9
|
+
|
|
10
|
+
# Test 1: Empty prompt should silently pass
|
|
11
|
+
OUT=$(echo '{"tool_input":{"prompt":""}}' | bash "$HOOK" 2>&1)
|
|
12
|
+
RC=$?
|
|
13
|
+
assert_not_contains "empty prompt no warning" "$OUT" "Subagent output verification"
|
|
14
|
+
assert_exit "empty prompt exit 0" "$RC" "0"
|
|
15
|
+
|
|
16
|
+
# Test 2: Vague prompt should warn on all 3 checks
|
|
17
|
+
OUT=$(echo '{"tool_input":{"prompt":"please investigate the auth flow"}}' | bash "$HOOK" 2>&1)
|
|
18
|
+
RC=$?
|
|
19
|
+
assert_contains "vague warns artifact" "$OUT" "No concrete artifact"
|
|
20
|
+
assert_contains "vague warns verification" "$OUT" "No artifact verification"
|
|
21
|
+
assert_contains "vague warns recommended" "$OUT" "Recommended:"
|
|
22
|
+
assert_contains "vague references issue" "$OUT" "#55666"
|
|
23
|
+
assert_exit "vague exit 0 advisory" "$RC" "0"
|
|
24
|
+
|
|
25
|
+
# Test 3: Artifact named, other 2 missing
|
|
26
|
+
OUT=$(echo '{"tool_input":{"prompt":"Write to /tmp/result.txt with the analysis."}}' | bash "$HOOK" 2>&1)
|
|
27
|
+
assert_not_contains "artifact only no artifact warning" "$OUT" "No concrete artifact"
|
|
28
|
+
assert_contains "artifact only warns verification" "$OUT" "No artifact verification"
|
|
29
|
+
|
|
30
|
+
# Test 4: Verification named, other 2 missing
|
|
31
|
+
OUT=$(echo '{"tool_input":{"prompt":"Investigate. I will verify the result."}}' | bash "$HOOK" 2>&1)
|
|
32
|
+
assert_contains "verify only warns artifact" "$OUT" "No concrete artifact"
|
|
33
|
+
assert_not_contains "verify only no verify warning" "$OUT" "No artifact verification"
|
|
34
|
+
|
|
35
|
+
# Test 5: Distrust phrase named, other 2 missing
|
|
36
|
+
OUT=$(echo '{"tool_input":{"prompt":"Do something. Do not trust reply-only success."}}' | bash "$HOOK" 2>&1)
|
|
37
|
+
assert_contains "distrust only warns artifact" "$OUT" "No concrete artifact"
|
|
38
|
+
assert_contains "distrust only warns verification" "$OUT" "No artifact verification"
|
|
39
|
+
assert_not_contains "distrust only no recommended warning" "$OUT" "Recommended:"
|
|
40
|
+
|
|
41
|
+
# Test 6: All 3 instructions present, no warning
|
|
42
|
+
OUT=$(echo '{"tool_input":{"prompt":"Write to /tmp/result.txt. I will verify the file exists. Do not reply success without producing the artifact."}}' | bash "$HOOK" 2>&1)
|
|
43
|
+
RC=$?
|
|
44
|
+
assert_not_contains "well-formed no warning" "$OUT" "Subagent output verification"
|
|
45
|
+
assert_exit "well-formed exit 0" "$RC" "0"
|
|
46
|
+
|
|
47
|
+
# Test 7: Strict mode blocks vague prompts
|
|
48
|
+
OUT=$(echo '{"tool_input":{"prompt":"investigate something"}}' | CC_SUBAGENT_VERIFY_REQUIRE_ALL=1 bash "$HOOK" 2>&1)
|
|
49
|
+
RC=$?
|
|
50
|
+
assert_contains "strict mode warns" "$OUT" "Subagent output verification"
|
|
51
|
+
assert_exit "strict mode blocks (exit 2)" "$RC" "2"
|
|
52
|
+
|
|
53
|
+
# Test 8: Missing prompt field should silently pass
|
|
54
|
+
OUT=$(echo '{}' | bash "$HOOK" 2>&1)
|
|
55
|
+
RC=$?
|
|
56
|
+
assert_not_contains "missing prompt no warning" "$OUT" "Subagent output verification"
|
|
57
|
+
assert_exit "missing prompt exit 0" "$RC" "0"
|
|
58
|
+
|
|
59
|
+
echo "Results: $PASS passed, $FAIL failed"
|
|
60
|
+
[ "$FAIL" -eq 0 ]
|