cc-safe-setup 29.6.32 → 29.6.33
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/COOKBOOK.md +70 -0
- package/README.md +6 -2
- package/examples/absolute-rule-enforcer.sh +42 -0
- package/examples/allow-claude-settings.sh +2 -0
- package/examples/allow-git-hooks-dir.sh +2 -0
- package/examples/allow-protected-dirs.sh +2 -0
- package/examples/allowlist.sh +2 -0
- package/examples/ansible-vault-guard.sh +2 -0
- package/examples/auto-approve-build.sh +2 -0
- package/examples/auto-approve-compound-git.sh +2 -0
- package/examples/auto-approve-docker.sh +2 -0
- package/examples/auto-approve-git-read.sh +2 -0
- package/examples/auto-approve-python.sh +2 -0
- package/examples/auto-approve-readonly-tools.sh +2 -0
- package/examples/auto-approve-ssh.sh +2 -0
- package/examples/auto-approve-test.sh +2 -0
- package/examples/auto-checkpoint.sh +2 -0
- package/examples/auto-git-checkpoint.sh +2 -0
- package/examples/auto-mode-safe-commands.sh +2 -0
- package/examples/auto-snapshot.sh +2 -0
- package/examples/backup-before-refactor.sh +2 -0
- package/examples/banned-command-guard.sh +3 -3
- package/examples/bash-domain-allowlist.sh +72 -0
- package/examples/bash-safety-auto-deny.sh +56 -0
- package/examples/bash-secret-output-detector.sh +68 -0
- package/examples/bash-timeout-guard.sh +2 -0
- package/examples/bashrc-safety-check.sh +59 -0
- package/examples/bg-task-cooldown-guard.sh +46 -0
- package/examples/block-database-wipe.sh +2 -0
- package/examples/branch-name-check.sh +2 -0
- package/examples/branch-naming-convention.sh +2 -0
- package/examples/cargo-publish-guard.sh +2 -0
- package/examples/check-abort-controller.sh +2 -0
- package/examples/check-accessibility.sh +2 -0
- package/examples/check-aria-labels.sh +2 -0
- package/examples/check-async-await-consistency.sh +2 -0
- package/examples/check-before-act-enforcer.sh +47 -0
- package/examples/check-charset-meta.sh +2 -0
- package/examples/check-cleanup-effect.sh +2 -0
- package/examples/check-content-type.sh +2 -0
- package/examples/check-controlled-input.sh +2 -0
- package/examples/check-cookie-flags.sh +2 -0
- package/examples/check-cors-config.sh +2 -0
- package/examples/check-csp-headers.sh +2 -0
- package/examples/check-csrf-protection.sh +2 -0
- package/examples/check-debounce.sh +2 -0
- package/examples/check-dependency-age.sh +2 -0
- package/examples/check-dependency-license.sh +2 -0
- package/examples/check-dockerfile-best-practice.sh +2 -0
- package/examples/check-error-boundaries.sh +2 -0
- package/examples/check-error-class.sh +2 -0
- package/examples/check-error-handling.sh +2 -0
- package/examples/check-error-logging.sh +2 -0
- package/examples/check-error-message.sh +2 -0
- package/examples/check-error-page.sh +2 -0
- package/examples/check-error-stack.sh +2 -0
- package/examples/check-favicon.sh +2 -0
- package/examples/check-form-validation.sh +2 -0
- package/examples/check-git-hooks-compat.sh +2 -0
- package/examples/check-https-redirect.sh +2 -0
- package/examples/check-image-optimization.sh +2 -0
- package/examples/check-input-validation.sh +2 -0
- package/examples/check-key-prop.sh +2 -0
- package/examples/check-lang-attribute.sh +2 -0
- package/examples/check-lazy-loading.sh +2 -0
- package/examples/check-loading-state.sh +2 -0
- package/examples/check-memo-deps.sh +2 -0
- package/examples/check-meta-description.sh +2 -0
- package/examples/check-npm-scripts-exist.sh +2 -0
- package/examples/check-null-check.sh +2 -0
- package/examples/check-package-size.sh +2 -0
- package/examples/check-pagination.sh +2 -0
- package/examples/check-port-availability.sh +2 -0
- package/examples/check-promise-all.sh +2 -0
- package/examples/check-prop-types.sh +2 -0
- package/examples/check-rate-limiting.sh +2 -0
- package/examples/check-responsive-design.sh +2 -0
- package/examples/check-retry-logic.sh +2 -0
- package/examples/check-return-types.sh +2 -0
- package/examples/check-semantic-html.sh +2 -0
- package/examples/check-semantic-versioning.sh +2 -0
- package/examples/check-suspense-fallback.sh +2 -0
- package/examples/check-test-naming.sh +2 -0
- package/examples/check-timeout-cleanup.sh +2 -0
- package/examples/check-tls-version.sh +2 -0
- package/examples/check-type-coercion.sh +2 -0
- package/examples/check-unsubscribe.sh +2 -0
- package/examples/check-viewport-meta.sh +2 -0
- package/examples/check-worker-terminate.sh +2 -0
- package/examples/checkpoint-tamper-guard.sh +2 -0
- package/examples/chmod-guard.sh +2 -0
- package/examples/chown-guard.sh +2 -0
- package/examples/ci-workflow-guard.sh +59 -0
- package/examples/classifier-fallback-allow.sh +2 -0
- package/examples/claude-cache-gc.sh +15 -0
- package/examples/claudeignore-enforce-guard.sh +60 -0
- package/examples/claudemd-enforcer.sh +2 -0
- package/examples/commit-message-check.sh +2 -0
- package/examples/compact-blocker.sh +25 -0
- package/examples/composer-guard.sh +2 -0
- package/examples/compound-command-allow.sh +2 -0
- package/examples/consecutive-failure-circuit-breaker.sh +49 -0
- package/examples/console-log-count.sh +2 -0
- package/examples/context-compact-advisor.sh +16 -0
- package/examples/cors-star-warn.sh +2 -0
- package/examples/credential-exfil-guard.sh +2 -0
- package/examples/credential-file-cat-guard.sh +2 -0
- package/examples/cron-modification-guard.sh +40 -0
- package/examples/cwd-project-boundary-guard.sh +50 -0
- package/examples/denied-action-retry-guard.sh +41 -0
- package/examples/dependency-install-guard.sh +2 -0
- package/examples/deploy-guard.sh +2 -0
- package/examples/deploy-path-verify-guard.sh +62 -0
- package/examples/django-migrate-guard.sh +2 -0
- package/examples/docker-volume-guard.sh +2 -0
- package/examples/dockerfile-latest-guard.sh +2 -0
- package/examples/dotenv-commit-guard.sh +44 -0
- package/examples/dotenv-example-sync.sh +55 -0
- package/examples/dotnet-build-on-edit.sh +2 -0
- package/examples/drizzle-migrate-guard.sh +2 -0
- package/examples/edit-counter-test-gate.sh +44 -0
- package/examples/edit-error-counter.sh +2 -0
- package/examples/edit-guard.sh +2 -0
- package/examples/edit-retry-loop-guard.sh +2 -0
- package/examples/edit-verify.sh +2 -0
- package/examples/enforce-tests.sh +2 -0
- package/examples/env-inherit-guard.sh +2 -0
- package/examples/env-inline-secret-guard.sh +36 -0
- package/examples/env-prod-guard.sh +2 -0
- package/examples/env-required-check.sh +2 -0
- package/examples/env-var-check.sh +2 -0
- package/examples/expo-eject-guard.sh +2 -0
- package/examples/export-overwrite-guard.sh +29 -0
- package/examples/file-change-tracker.sh +2 -0
- package/examples/file-change-undo-tracker.sh +46 -0
- package/examples/file-recycle-bin.sh +48 -0
- package/examples/file-size-limit.sh +2 -0
- package/examples/five-hundred-milestone.sh +2 -0
- package/examples/flask-debug-guard.sh +2 -0
- package/examples/gem-push-guard.sh +2 -0
- package/examples/git-checkout-safety-guard.sh +2 -0
- package/examples/git-config-guard.sh +2 -0
- package/examples/git-hook-bypass-guard.sh +2 -0
- package/examples/git-merge-conflict-prevent.sh +2 -0
- package/examples/git-message-length.sh +2 -0
- package/examples/git-show-flag-sanitizer.sh +41 -0
- package/examples/git-stash-before-danger.sh +2 -0
- package/examples/git-submodule-guard.sh +2 -0
- package/examples/git-tag-guard.sh +2 -0
- package/examples/github-actions-secret-guard.sh +59 -0
- package/examples/gitignore-check.sh +2 -0
- package/examples/gitops-drift-guard.sh +53 -0
- package/examples/go-mod-tidy-warn.sh +2 -0
- package/examples/hallucination-url-check.sh +2 -0
- package/examples/hardcoded-ip-guard.sh +2 -0
- package/examples/headless-empty-result-guard.sh +46 -0
- package/examples/headless-stop-guard.sh +43 -0
- package/examples/helm-install-guard.sh +2 -0
- package/examples/issue-draft-redact-guard.sh +45 -0
- package/examples/java-compile-on-edit.sh +2 -0
- package/examples/k8s-production-guard.sh +77 -0
- package/examples/laravel-artisan-guard.sh +2 -0
- package/examples/large-file-guard.sh +2 -0
- package/examples/log-level-guard.sh +2 -0
- package/examples/magic-number-warn.sh +2 -0
- package/examples/max-edit-size-guard.sh +2 -0
- package/examples/max-file-count-guard.sh +2 -0
- package/examples/max-file-delete-count.sh +2 -0
- package/examples/max-function-length.sh +2 -0
- package/examples/max-import-count.sh +2 -0
- package/examples/max-subagent-count.sh +2 -0
- package/examples/mcp-orphan-process-guard.sh +39 -0
- package/examples/mcp-server-allowlist.sh +45 -0
- package/examples/mcp-tool-audit-log.sh +41 -0
- package/examples/mcp-tool-guard.sh +2 -0
- package/examples/migration-verify-guard.sh +44 -0
- package/examples/monorepo-scope-guard.sh +2 -0
- package/examples/network-exfil-guard.sh +61 -0
- package/examples/network-guard.sh +2 -0
- package/examples/nextjs-env-guard.sh +2 -0
- package/examples/no-absolute-import.sh +2 -0
- package/examples/no-alert-confirm-prompt.sh +2 -0
- package/examples/no-any-type.sh +2 -0
- package/examples/no-any-typescript.sh +2 -0
- package/examples/no-assignment-in-condition.sh +2 -0
- package/examples/no-callback-hell.sh +2 -0
- package/examples/no-catch-all-route.sh +2 -0
- package/examples/no-circular-dependency.sh +2 -0
- package/examples/no-class-in-functional.sh +2 -0
- package/examples/no-cleartext-storage.sh +2 -0
- package/examples/no-commented-code.sh +2 -0
- package/examples/no-commit-fixup.sh +2 -0
- package/examples/no-console-assert.sh +2 -0
- package/examples/no-console-error-swallow.sh +2 -0
- package/examples/no-console-in-prod.sh +2 -0
- package/examples/no-console-log.sh +2 -0
- package/examples/no-console-time.sh +2 -0
- package/examples/no-cors-wildcard.sh +2 -0
- package/examples/no-curl-upload.sh +2 -0
- package/examples/no-dangerouslySetInnerHTML.sh +2 -0
- package/examples/no-dangling-await.sh +2 -0
- package/examples/no-debug-in-commit.sh +2 -0
- package/examples/no-deep-nesting.sh +2 -0
- package/examples/no-deep-relative-import.sh +2 -0
- package/examples/no-default-credentials.sh +2 -0
- package/examples/no-deprecated-api.sh +2 -0
- package/examples/no-direct-dom-manipulation.sh +2 -0
- package/examples/no-disabled-test.sh +2 -0
- package/examples/no-document-cookie.sh +2 -0
- package/examples/no-document-write.sh +2 -0
- package/examples/no-empty-function.sh +2 -0
- package/examples/no-eval-in-template.sh +2 -0
- package/examples/no-eval-template.sh +2 -0
- package/examples/no-eval.sh +2 -0
- package/examples/no-exec-user-input.sh +2 -0
- package/examples/no-expose-internal-ids.sh +2 -0
- package/examples/no-floating-promises.sh +2 -0
- package/examples/no-force-install.sh +2 -0
- package/examples/no-git-rebase-public.sh +2 -0
- package/examples/no-global-state.sh +2 -0
- package/examples/no-hardcoded-port.sh +2 -0
- package/examples/no-hardcoded-url.sh +2 -0
- package/examples/no-helmet-missing.sh +2 -0
- package/examples/no-http-url.sh +2 -0
- package/examples/no-http-without-https.sh +2 -0
- package/examples/no-index-as-key.sh +2 -0
- package/examples/no-infinite-scroll-mem.sh +2 -0
- package/examples/no-inline-event-handler.sh +2 -0
- package/examples/no-inline-handler.sh +2 -0
- package/examples/no-inline-style.sh +2 -0
- package/examples/no-inline-styles.sh +2 -0
- package/examples/no-innerhtml.sh +2 -0
- package/examples/no-install-global.sh +2 -0
- package/examples/no-jwt-in-url.sh +2 -0
- package/examples/no-large-commit.sh +2 -0
- package/examples/no-localhost-expose.sh +2 -0
- package/examples/no-long-switch.sh +2 -0
- package/examples/no-magic-number.sh +2 -0
- package/examples/no-md5-sha1.sh +2 -0
- package/examples/no-memory-leak-interval.sh +2 -0
- package/examples/no-mixed-line-endings.sh +2 -0
- package/examples/no-mutation-in-reducer.sh +2 -0
- package/examples/no-mutation-observer-leak.sh +2 -0
- package/examples/no-nested-subscribe.sh +2 -0
- package/examples/no-nested-ternary.sh +2 -0
- package/examples/no-network-exfil.sh +2 -0
- package/examples/no-new-array-fill.sh +2 -0
- package/examples/no-object-freeze-mutation.sh +2 -0
- package/examples/no-open-redirect.sh +2 -0
- package/examples/no-output-truncation.sh +44 -0
- package/examples/no-package-downgrade.sh +2 -0
- package/examples/no-package-lock-edit.sh +2 -0
- package/examples/no-path-join-user-input.sh +2 -0
- package/examples/no-port-bind.sh +2 -0
- package/examples/no-process-exit.sh +2 -0
- package/examples/no-prototype-pollution.sh +2 -0
- package/examples/no-push-without-ci.sh +2 -0
- package/examples/no-raw-ref.sh +2 -0
- package/examples/no-redundant-fragment.sh +2 -0
- package/examples/no-render-in-loop.sh +2 -0
- package/examples/no-root-user-docker.sh +2 -0
- package/examples/no-root-write.sh +2 -0
- package/examples/no-secrets-in-args.sh +2 -0
- package/examples/no-secrets-in-logs.sh +2 -0
- package/examples/no-sensitive-log.sh +2 -0
- package/examples/no-side-effects-in-render.sh +2 -0
- package/examples/no-sleep-in-hooks.sh +2 -0
- package/examples/no-star-import-python.sh +2 -0
- package/examples/no-string-concat-sql.sh +2 -0
- package/examples/no-sudo-guard.sh +2 -0
- package/examples/no-sync-external-call.sh +2 -0
- package/examples/no-sync-fs.sh +2 -0
- package/examples/no-table-layout.sh +2 -0
- package/examples/no-throw-string.sh +2 -0
- package/examples/no-todo-in-merge.sh +2 -0
- package/examples/no-todo-in-production.sh +2 -0
- package/examples/no-todo-without-issue.sh +2 -0
- package/examples/no-triple-slash-ref.sh +2 -0
- package/examples/no-unreachable-code.sh +2 -0
- package/examples/no-unused-import.sh +2 -0
- package/examples/no-unused-state.sh +2 -0
- package/examples/no-var-keyword.sh +2 -0
- package/examples/no-wildcard-cors.sh +2 -0
- package/examples/no-wildcard-import.sh +2 -0
- package/examples/no-window-location.sh +2 -0
- package/examples/no-with-statement.sh +2 -0
- package/examples/no-write-outside-src.sh +2 -0
- package/examples/no-xml-external-entity.sh +2 -0
- package/examples/notify-waiting.sh +2 -0
- package/examples/npm-audit-warn.sh +2 -0
- package/examples/npm-publish-guard.sh +2 -0
- package/examples/npm-script-injection.sh +2 -0
- package/examples/npm-supply-chain-guard.sh +92 -0
- package/examples/nuxt-config-guard.sh +2 -0
- package/examples/output-secret-mask.sh +2 -0
- package/examples/package-json-guard.sh +2 -0
- package/examples/parallel-session-guard.sh +2 -0
- package/examples/path-traversal-guard.sh +2 -0
- package/examples/permission-audit-log.sh +2 -0
- package/examples/permission-entry-validator.sh +48 -0
- package/examples/php-lint-on-edit.sh +2 -0
- package/examples/pip-publish-guard.sh +2 -0
- package/examples/plain-language-danger-warn.sh +37 -0
- package/examples/plan-mode-enforcer.sh +2 -0
- package/examples/plugin-process-cleanup.sh +50 -0
- package/examples/polyglot-rm-guard.sh +59 -0
- package/examples/pr-description-check.sh +2 -0
- package/examples/pre-compact-knowledge-save.sh +53 -0
- package/examples/pre-compact-transcript-export.sh +85 -0
- package/examples/prefer-builtin-tools.sh +2 -0
- package/examples/prefer-const.sh +2 -0
- package/examples/prefer-dedicated-tools.sh +55 -0
- package/examples/prefer-optional-chaining.sh +2 -0
- package/examples/prisma-migrate-guard.sh +2 -0
- package/examples/prompt-injection-detector.sh +2 -0
- package/examples/prompt-length-guard.sh +2 -0
- package/examples/protect-dotfiles.sh +2 -0
- package/examples/public-repo-push-guard.sh +58 -0
- package/examples/push-requires-test-pass-record.sh +2 -0
- package/examples/push-requires-test-pass.sh +2 -0
- package/examples/rails-migration-guard.sh +2 -0
- package/examples/rate-limit-guard.sh +2 -0
- package/examples/read-all-files-enforcer.sh +51 -0
- package/examples/readme-exists-check.sh +2 -0
- package/examples/redis-flushall-guard.sh +2 -0
- package/examples/rm-safety-net.sh +2 -0
- package/examples/role-tool-guard.sh +69 -0
- package/examples/ruby-lint-on-edit.sh +2 -0
- package/examples/schema-migration-guard.sh +57 -0
- package/examples/scope-guard.sh +2 -0
- package/examples/secret-file-read-guard.sh +74 -0
- package/examples/self-modify-bypass-guard.sh +54 -0
- package/examples/sensitive-log-guard.sh +2 -0
- package/examples/session-checkpoint.sh +2 -0
- package/examples/session-end-logger.sh +57 -0
- package/examples/session-error-rate-monitor.sh +65 -0
- package/examples/session-health-monitor.sh +61 -0
- package/examples/session-memory-watchdog.sh +17 -0
- package/examples/session-permission-reset-guard.sh +39 -0
- package/examples/session-resume-env-fix.sh +49 -0
- package/examples/session-state-saver.sh +2 -0
- package/examples/session-summary-stop.sh +2 -0
- package/examples/session-summary.sh +2 -0
- package/examples/session-token-counter.sh +2 -0
- package/examples/shell-wrapper-guard.sh +2 -0
- package/examples/skill-gate.sh +2 -0
- package/examples/skill-injection-detector.sh +41 -0
- package/examples/spec-file-scope-guard.sh +69 -0
- package/examples/spring-profile-guard.sh +2 -0
- package/examples/sql-injection-detect.sh +2 -0
- package/examples/subagent-budget-guard.sh +2 -0
- package/examples/subagent-claudemd-inject.sh +45 -0
- package/examples/subagent-tool-call-limiter.sh +48 -0
- package/examples/svelte-lint-on-edit.sh +2 -0
- package/examples/swift-build-on-edit.sh +2 -0
- package/examples/system-message-workaround.sh +44 -0
- package/examples/system-package-guard.sh +2 -0
- package/examples/temp-file-cleanup.sh +2 -0
- package/examples/terminal-state-restore.sh +23 -0
- package/examples/test-after-edit.sh +2 -0
- package/examples/test-before-commit.sh +2 -0
- package/examples/test-before-push.sh +2 -0
- package/examples/test-exit-code-verify.sh +2 -0
- package/examples/timeout-guard.sh +2 -0
- package/examples/timezone-guard.sh +2 -0
- package/examples/tmp-output-size-guard.sh +46 -0
- package/examples/todo-check.sh +2 -0
- package/examples/todo-deadline-warn.sh +48 -0
- package/examples/token-budget-per-task.sh +55 -0
- package/examples/token-usage-tracker.sh +14 -0
- package/examples/turbo-cache-guard.sh +2 -0
- package/examples/uncommitted-changes-stop.sh +2 -0
- package/examples/uncommitted-work-shield.sh +37 -0
- package/examples/usage-warn.sh +2 -0
- package/examples/verify-before-commit.sh +2 -0
- package/examples/vue-lint-on-edit.sh +2 -0
- package/examples/webfetch-domain-allow.sh +96 -0
- package/examples/worktree-memory-guard.sh +47 -0
- package/examples/worktree-project-unify.sh +19 -0
- package/examples/worktree-unmerged-guard.sh +2 -0
- package/examples/write-overwrite-confirm.sh +40 -0
- package/examples/write-secret-guard.sh +2 -0
- package/examples/write-test-ratio.sh +2 -0
- package/package.json +2 -2
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# headless-stop-guard.sh — Skip Stop hooks in headless (-p) mode
|
|
3
|
+
#
|
|
4
|
+
# Solves: Stop hook causes empty result in print mode (#38651).
|
|
5
|
+
# Any Stop hook (even no-op) causes `claude -p` to return
|
|
6
|
+
# empty string instead of the model's response.
|
|
7
|
+
#
|
|
8
|
+
# How it works: Detects headless mode via parent process inspection
|
|
9
|
+
# and exits immediately, preventing the Stop hook from interfering
|
|
10
|
+
# with result collection.
|
|
11
|
+
#
|
|
12
|
+
# TRIGGER: Stop
|
|
13
|
+
# MATCHER: ""
|
|
14
|
+
#
|
|
15
|
+
# Usage: Use as a wrapper around your actual Stop hook:
|
|
16
|
+
# {
|
|
17
|
+
# "hooks": {
|
|
18
|
+
# "Stop": [{
|
|
19
|
+
# "hooks": [{ "type": "command", "command": "bash ~/.claude/hooks/headless-stop-guard.sh ~/.claude/hooks/my-stop-hook.sh" }]
|
|
20
|
+
# }]
|
|
21
|
+
# }
|
|
22
|
+
# }
|
|
23
|
+
#
|
|
24
|
+
# Or set CC_HEADLESS=1 in your wrapper script before `claude -p`.
|
|
25
|
+
|
|
26
|
+
# Method 1: Environment variable (most reliable)
|
|
27
|
+
[ "$CC_HEADLESS" = "1" ] && exit 0
|
|
28
|
+
|
|
29
|
+
# Method 2: Parent process detection
|
|
30
|
+
PARENT_CMD=$(ps -o args= -p $PPID 2>/dev/null || true)
|
|
31
|
+
if echo "$PARENT_CMD" | grep -qE '\bclaude\b.*\s-p\b'; then
|
|
32
|
+
exit 0
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
# Not headless — run the wrapped hook if provided
|
|
36
|
+
TARGET="$1"
|
|
37
|
+
if [ -n "$TARGET" ] && [ -f "$TARGET" ]; then
|
|
38
|
+
shift
|
|
39
|
+
cat | bash "$TARGET" "$@"
|
|
40
|
+
exit $?
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
exit 0
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# issue-draft-redact-guard.sh — Redact sensitive info from public issue drafts
|
|
3
|
+
#
|
|
4
|
+
# Solves: Claude drafting public bug reports with sensitive project info (#29121).
|
|
5
|
+
# Internal org names, private URLs, IP addresses, and file paths
|
|
6
|
+
# get included in gh issue create commands.
|
|
7
|
+
#
|
|
8
|
+
# How it works: PreToolUse hook on Bash that intercepts gh issue/pr create
|
|
9
|
+
# commands and scans the body for sensitive patterns.
|
|
10
|
+
#
|
|
11
|
+
# TRIGGER: PreToolUse
|
|
12
|
+
# MATCHER: "Bash"
|
|
13
|
+
|
|
14
|
+
set -euo pipefail
|
|
15
|
+
|
|
16
|
+
INPUT=$(cat)
|
|
17
|
+
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
18
|
+
[ -z "$COMMAND" ] && exit 0
|
|
19
|
+
|
|
20
|
+
# Only check issue/PR creation commands
|
|
21
|
+
if ! echo "$COMMAND" | grep -qE 'gh\s+(issue|pr)\s+create'; then
|
|
22
|
+
exit 0
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
# Scan for sensitive patterns in the command body
|
|
26
|
+
SENSITIVE_PATTERNS=(
|
|
27
|
+
'[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' # IP addresses
|
|
28
|
+
'(internal|private|corp|staging)\.[a-z]+\.[a-z]+' # Internal domains
|
|
29
|
+
'/home/[a-zA-Z]+/' # Home directory paths
|
|
30
|
+
'/Users/[a-zA-Z]+/' # macOS home paths
|
|
31
|
+
'password|passwd|secret_key|private_key' # Secret keywords
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
for pattern in "${SENSITIVE_PATTERNS[@]}"; do
|
|
35
|
+
if echo "$COMMAND" | grep -qEi "$pattern"; then
|
|
36
|
+
MATCH=$(echo "$COMMAND" | grep -oEi "$pattern" | head -1)
|
|
37
|
+
echo "WARNING: Sensitive pattern detected in issue draft." >&2
|
|
38
|
+
echo "Pattern match: $MATCH" >&2
|
|
39
|
+
echo "Review and redact before posting publicly." >&2
|
|
40
|
+
# Warn but don't block — user may intentionally include their own info
|
|
41
|
+
break
|
|
42
|
+
fi
|
|
43
|
+
done
|
|
44
|
+
|
|
45
|
+
exit 0
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# k8s-production-guard.sh — Block destructive Kubernetes operations on production
|
|
3
|
+
#
|
|
4
|
+
# Solves: Claude running kubectl delete, scale-to-zero, or rollback on
|
|
5
|
+
# production namespaces/clusters without explicit confirmation.
|
|
6
|
+
#
|
|
7
|
+
# How it works: PreToolUse hook on Bash that detects kubectl/helm commands
|
|
8
|
+
# targeting production contexts/namespaces and blocks destructive operations.
|
|
9
|
+
#
|
|
10
|
+
# CONFIG:
|
|
11
|
+
# CC_K8S_PROD_CONTEXTS="prod:production:live" (colon-separated)
|
|
12
|
+
# CC_K8S_PROD_NAMESPACES="production:prod:default" (colon-separated)
|
|
13
|
+
#
|
|
14
|
+
# TRIGGER: PreToolUse
|
|
15
|
+
# MATCHER: "Bash"
|
|
16
|
+
|
|
17
|
+
set -euo pipefail
|
|
18
|
+
|
|
19
|
+
INPUT=$(cat)
|
|
20
|
+
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
21
|
+
[ -z "$COMMAND" ] && exit 0
|
|
22
|
+
|
|
23
|
+
# Only check kubectl/helm commands
|
|
24
|
+
echo "$COMMAND" | grep -qE '(kubectl|helm)\s' || exit 0
|
|
25
|
+
|
|
26
|
+
# Production indicators
|
|
27
|
+
PROD_CTX="${CC_K8S_PROD_CONTEXTS:-prod:production:live}"
|
|
28
|
+
PROD_NS="${CC_K8S_PROD_NAMESPACES:-production:prod}"
|
|
29
|
+
|
|
30
|
+
# Destructive kubectl operations
|
|
31
|
+
DESTRUCT_KUBECTL='delete\s+(deploy|pod|svc|namespace|pv|statefulset|daemonset|job|cronjob|ingress|secret|configmap)|scale\s+.*--replicas=0|drain\s|cordon\s|taint\s.*NoSchedule|rollout\s+undo'
|
|
32
|
+
|
|
33
|
+
# Destructive helm operations
|
|
34
|
+
DESTRUCT_HELM='helm\s+(uninstall|delete|rollback|reset)'
|
|
35
|
+
|
|
36
|
+
# Check if command is destructive
|
|
37
|
+
IS_DESTRUCTIVE=false
|
|
38
|
+
if echo "$COMMAND" | grep -qE "$DESTRUCT_KUBECTL"; then
|
|
39
|
+
IS_DESTRUCTIVE=true
|
|
40
|
+
fi
|
|
41
|
+
if echo "$COMMAND" | grep -qE "$DESTRUCT_HELM"; then
|
|
42
|
+
IS_DESTRUCTIVE=true
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
$IS_DESTRUCTIVE || exit 0
|
|
46
|
+
|
|
47
|
+
# Check if targeting production
|
|
48
|
+
IS_PROD=false
|
|
49
|
+
|
|
50
|
+
# Check --context flag
|
|
51
|
+
IFS=':' read -ra CTXS <<< "$PROD_CTX"
|
|
52
|
+
for ctx in "${CTXS[@]}"; do
|
|
53
|
+
if echo "$COMMAND" | grep -qE -- "--context[= ]$ctx"; then
|
|
54
|
+
IS_PROD=true
|
|
55
|
+
break
|
|
56
|
+
fi
|
|
57
|
+
done
|
|
58
|
+
|
|
59
|
+
# Check -n/--namespace flag
|
|
60
|
+
IFS=':' read -ra NSS <<< "$PROD_NS"
|
|
61
|
+
for ns in "${NSS[@]}"; do
|
|
62
|
+
if echo "$COMMAND" | grep -qE -- "(-n|--namespace)[= ]$ns"; then
|
|
63
|
+
IS_PROD=true
|
|
64
|
+
break
|
|
65
|
+
fi
|
|
66
|
+
done
|
|
67
|
+
|
|
68
|
+
if $IS_PROD; then
|
|
69
|
+
echo "BLOCKED: Destructive Kubernetes operation on production." >&2
|
|
70
|
+
echo " Command: $COMMAND" >&2
|
|
71
|
+
echo " Run this manually if you're sure." >&2
|
|
72
|
+
exit 2
|
|
73
|
+
fi
|
|
74
|
+
|
|
75
|
+
# Not targeting production explicitly — warn but allow
|
|
76
|
+
echo "NOTE: Destructive k8s operation (not targeting a known prod namespace)." >&2
|
|
77
|
+
exit 0
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# TRIGGER: PreToolUse MATCHER: "Bash"
|
|
2
4
|
COMMAND=$(cat | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
3
5
|
[ -z "$COMMAND" ] && exit 0
|
|
4
6
|
if echo "$COMMAND" | grep -qE "^\s*rm\b"; then COUNT=$(echo "$COMMAND" | tr " " "\n" | grep -cvE "^-" | head -1); [ "$COUNT" -gt 5 ] && echo "WARNING: Deleting $COUNT files at once" >&2; fi
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# TRIGGER: PreToolUse MATCHER: "Edit|Write"
|
|
2
4
|
CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
|
|
3
5
|
[ -z "$CONTENT" ] && exit 0
|
|
4
6
|
IMPORTS=$(echo "$CONTENT" | grep -cE "^(import|from|require)" || echo 0); [ "$IMPORTS" -gt 20 ] && echo "NOTE: $IMPORTS imports — consider splitting module" >&2
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# TRIGGER: PreToolUse MATCHER: "Bash"
|
|
2
4
|
COMMAND=$(cat | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
3
5
|
[ -z "$COMMAND" ] && exit 0
|
|
4
6
|
STATE="/tmp/cc-subagent-count"; C=$(cat "$STATE" 2>/dev/null || echo 0); echo $((C+1)) > "$STATE"; [ "$C" -gt 5 ] && echo "WARNING: $C subagents spawned this session" >&2
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# mcp-orphan-process-guard.sh — Detect orphaned MCP server processes
|
|
3
|
+
#
|
|
4
|
+
# Solves: MCP server containers not stopped when Claude Code exits (#29058).
|
|
5
|
+
# Docker containers and background processes accumulate over sessions.
|
|
6
|
+
#
|
|
7
|
+
# How it works: Stop hook that checks for running MCP-related processes
|
|
8
|
+
# and warns about potential orphans.
|
|
9
|
+
#
|
|
10
|
+
# TRIGGER: Stop
|
|
11
|
+
# MATCHER: ""
|
|
12
|
+
|
|
13
|
+
set -euo pipefail
|
|
14
|
+
|
|
15
|
+
# Check for running MCP-related processes
|
|
16
|
+
ORPHANS=""
|
|
17
|
+
|
|
18
|
+
# Docker containers with MCP-like names
|
|
19
|
+
if command -v docker &>/dev/null; then
|
|
20
|
+
MCP_CONTAINERS=$(docker ps --format '{{.Names}}' 2>/dev/null | grep -iE 'mcp|claude|anthropic' || true)
|
|
21
|
+
if [ -n "$MCP_CONTAINERS" ]; then
|
|
22
|
+
ORPHANS="${ORPHANS}Docker containers: ${MCP_CONTAINERS}\n"
|
|
23
|
+
fi
|
|
24
|
+
fi
|
|
25
|
+
|
|
26
|
+
# Node/Python processes that might be MCP servers
|
|
27
|
+
MCP_PROCS=$(ps aux 2>/dev/null | grep -iE 'mcp.*server|@modelcontextprotocol' | grep -v grep || true)
|
|
28
|
+
if [ -n "$MCP_PROCS" ]; then
|
|
29
|
+
COUNT=$(echo "$MCP_PROCS" | wc -l)
|
|
30
|
+
ORPHANS="${ORPHANS}MCP processes: ${COUNT} running\n"
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
if [ -n "$ORPHANS" ]; then
|
|
34
|
+
echo "WARNING: Potential orphaned MCP processes detected:" >&2
|
|
35
|
+
echo -e "$ORPHANS" >&2
|
|
36
|
+
echo "Consider stopping them: docker stop <name> or kill <pid>" >&2
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
exit 0
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# mcp-server-allowlist.sh — Restrict MCP tool calls to allowed servers
|
|
3
|
+
#
|
|
4
|
+
# Solves: Unwanted MCP servers (synced from claude.ai) injecting tools
|
|
5
|
+
# that consume memory and cause OOM crashes (#20412).
|
|
6
|
+
# Also prevents untrusted MCP tools from being called.
|
|
7
|
+
#
|
|
8
|
+
# How it works: PreToolUse hook that checks if a tool call is from an
|
|
9
|
+
# MCP server, and blocks it if the server isn't in the allowlist.
|
|
10
|
+
#
|
|
11
|
+
# CONFIG:
|
|
12
|
+
# CC_MCP_ALLOWED="filesystem:github:memory" (colon-separated server names)
|
|
13
|
+
#
|
|
14
|
+
# TRIGGER: PreToolUse
|
|
15
|
+
# MATCHER: ""
|
|
16
|
+
|
|
17
|
+
set -euo pipefail
|
|
18
|
+
|
|
19
|
+
INPUT=$(cat)
|
|
20
|
+
TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
|
|
21
|
+
[ -z "$TOOL" ] && exit 0
|
|
22
|
+
|
|
23
|
+
ALLOWED="${CC_MCP_ALLOWED:-}"
|
|
24
|
+
[ -n "$ALLOWED" ] || exit 0 # No allowlist = allow all
|
|
25
|
+
|
|
26
|
+
# MCP tools are prefixed with mcp__servername__
|
|
27
|
+
case "$TOOL" in
|
|
28
|
+
mcp__*__*)
|
|
29
|
+
# Extract server name
|
|
30
|
+
SERVER=$(echo "$TOOL" | sed 's/^mcp__\([^_]*\)__.*/\1/')
|
|
31
|
+
|
|
32
|
+
IFS=':' read -ra SERVERS <<< "$ALLOWED"
|
|
33
|
+
for s in "${SERVERS[@]}"; do
|
|
34
|
+
[ "$s" = "$SERVER" ] && exit 0
|
|
35
|
+
done
|
|
36
|
+
|
|
37
|
+
echo "BLOCKED: MCP tool from non-allowed server '$SERVER'." >&2
|
|
38
|
+
echo " Tool: $TOOL" >&2
|
|
39
|
+
echo " Allowed servers: $ALLOWED" >&2
|
|
40
|
+
echo " Add to CC_MCP_ALLOWED to permit." >&2
|
|
41
|
+
exit 2
|
|
42
|
+
;;
|
|
43
|
+
esac
|
|
44
|
+
|
|
45
|
+
exit 0
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# mcp-tool-audit-log.sh — Log all MCP tool calls for security auditing
|
|
3
|
+
#
|
|
4
|
+
# Solves: No visibility into which MCP tools are being called, by whom,
|
|
5
|
+
# and with what parameters. Essential for OWASP MCP Top 10
|
|
6
|
+
# compliance (MCP09: Insufficient Logging).
|
|
7
|
+
#
|
|
8
|
+
# How it works: PostToolUse hook that logs MCP tool calls to a file
|
|
9
|
+
# with timestamp, tool name, server, and input summary.
|
|
10
|
+
#
|
|
11
|
+
# CONFIG:
|
|
12
|
+
# CC_MCP_AUDIT_LOG="~/.claude/mcp-audit.log"
|
|
13
|
+
#
|
|
14
|
+
# TRIGGER: PostToolUse
|
|
15
|
+
# MATCHER: ""
|
|
16
|
+
|
|
17
|
+
set -euo pipefail
|
|
18
|
+
|
|
19
|
+
INPUT=$(cat)
|
|
20
|
+
TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
|
|
21
|
+
[ -z "$TOOL" ] && exit 0
|
|
22
|
+
|
|
23
|
+
# Only log MCP tool calls
|
|
24
|
+
case "$TOOL" in
|
|
25
|
+
mcp__*) ;;
|
|
26
|
+
*) exit 0 ;;
|
|
27
|
+
esac
|
|
28
|
+
|
|
29
|
+
LOG_FILE="${CC_MCP_AUDIT_LOG:-${HOME}/.claude/mcp-audit.log}"
|
|
30
|
+
mkdir -p "$(dirname "$LOG_FILE")"
|
|
31
|
+
|
|
32
|
+
# Extract details
|
|
33
|
+
SERVER=$(echo "$TOOL" | sed 's/^mcp__\([^_]*\)__.*/\1/')
|
|
34
|
+
OPERATION=$(echo "$TOOL" | sed 's/^mcp__[^_]*__//')
|
|
35
|
+
EXIT_CODE=$(echo "$INPUT" | jq -r '.tool_result.exitCode // "0"' 2>/dev/null)
|
|
36
|
+
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
37
|
+
|
|
38
|
+
# Log entry
|
|
39
|
+
echo "${TIMESTAMP} | server=${SERVER} | op=${OPERATION} | exit=${EXIT_CODE} | tool=${TOOL}" >> "$LOG_FILE"
|
|
40
|
+
|
|
41
|
+
exit 0
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# migration-verify-guard.sh — Require verification before destructive migrations
|
|
3
|
+
#
|
|
4
|
+
# Solves: Claude executing destructive database/code migrations without
|
|
5
|
+
# verifying the plan first (#35435). A Rust migration went wrong
|
|
6
|
+
# across 2 sessions with 20 compounding errors.
|
|
7
|
+
#
|
|
8
|
+
# How it works: PreToolUse hook on Bash that detects migration commands
|
|
9
|
+
# and blocks them unless a verification marker file exists.
|
|
10
|
+
# Create the marker: touch .claude/migration-approved
|
|
11
|
+
#
|
|
12
|
+
# TRIGGER: PreToolUse
|
|
13
|
+
# MATCHER: "Bash"
|
|
14
|
+
|
|
15
|
+
set -euo pipefail
|
|
16
|
+
|
|
17
|
+
INPUT=$(cat)
|
|
18
|
+
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
19
|
+
[ -z "$COMMAND" ] && exit 0
|
|
20
|
+
|
|
21
|
+
# Detect migration commands across frameworks
|
|
22
|
+
MIGRATION_PATTERN='(migrate|migration|db:migrate|typeorm.*migration|prisma.*migrate|alembic|flyway|liquibase|knex.*migrate|sequelize.*db:migrate|rails.*db:migrate|django.*migrate|drizzle.*push)'
|
|
23
|
+
|
|
24
|
+
if echo "$COMMAND" | grep -qiE "$MIGRATION_PATTERN"; then
|
|
25
|
+
# Check for approval marker
|
|
26
|
+
if [ -f ".claude/migration-approved" ]; then
|
|
27
|
+
# Consume the marker (one-time use)
|
|
28
|
+
rm -f ".claude/migration-approved"
|
|
29
|
+
exit 0
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
echo "BLOCKED: Migration command detected without verification." >&2
|
|
33
|
+
echo "" >&2
|
|
34
|
+
echo "Command: $COMMAND" >&2
|
|
35
|
+
echo "" >&2
|
|
36
|
+
echo "Before running migrations:" >&2
|
|
37
|
+
echo " 1. Review the migration plan carefully" >&2
|
|
38
|
+
echo " 2. Ensure you have a backup or can rollback" >&2
|
|
39
|
+
echo " 3. Create approval: touch .claude/migration-approved" >&2
|
|
40
|
+
echo " 4. Then retry the command" >&2
|
|
41
|
+
exit 2
|
|
42
|
+
fi
|
|
43
|
+
|
|
44
|
+
exit 0
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# network-exfil-guard.sh — Block data exfiltration via network commands
|
|
3
|
+
#
|
|
4
|
+
# Solves: Claude using curl/wget/nc to send local data to external servers.
|
|
5
|
+
# OWASP MCP Top 10: MCP01 (Secret Exposure via network).
|
|
6
|
+
#
|
|
7
|
+
# How it works: PreToolUse hook on Bash that detects outbound data transfer
|
|
8
|
+
# commands (POST/PUT with file data, netcat connections, base64-encoded
|
|
9
|
+
# data in URLs) and blocks them.
|
|
10
|
+
#
|
|
11
|
+
# TRIGGER: PreToolUse
|
|
12
|
+
# MATCHER: "Bash"
|
|
13
|
+
|
|
14
|
+
set -euo pipefail
|
|
15
|
+
|
|
16
|
+
INPUT=$(cat)
|
|
17
|
+
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
18
|
+
[ -z "$COMMAND" ] && exit 0
|
|
19
|
+
|
|
20
|
+
# Patterns for outbound data exfiltration
|
|
21
|
+
BLOCKED=false
|
|
22
|
+
REASON=""
|
|
23
|
+
|
|
24
|
+
# curl/wget sending file contents
|
|
25
|
+
if echo "$COMMAND" | grep -qE 'curl\s+.*(-d\s+@|-F\s+.*=@|--data-binary\s+@|--upload-file)'; then
|
|
26
|
+
BLOCKED=true
|
|
27
|
+
REASON="curl uploading local file"
|
|
28
|
+
fi
|
|
29
|
+
|
|
30
|
+
# wget POST with file
|
|
31
|
+
if echo "$COMMAND" | grep -qE 'wget\s+.*--post-file'; then
|
|
32
|
+
BLOCKED=true
|
|
33
|
+
REASON="wget posting local file"
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
# netcat sending data
|
|
37
|
+
if echo "$COMMAND" | grep -qE '(nc|ncat|netcat)\s+.*<\s|>\s*(nc|ncat|netcat)'; then
|
|
38
|
+
BLOCKED=true
|
|
39
|
+
REASON="netcat data transfer"
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
# Pipe sensitive files to network commands
|
|
43
|
+
if echo "$COMMAND" | grep -qE 'cat\s+(~/\.|/etc/|/home/).*\|\s*(curl|wget|nc)'; then
|
|
44
|
+
BLOCKED=true
|
|
45
|
+
REASON="piping sensitive file to network command"
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
# Base64-encoded data in URL (common exfil technique)
|
|
49
|
+
if echo "$COMMAND" | grep -qE 'base64.*\|\s*curl|curl.*\$\(.*base64'; then
|
|
50
|
+
BLOCKED=true
|
|
51
|
+
REASON="base64-encoded data in network request"
|
|
52
|
+
fi
|
|
53
|
+
|
|
54
|
+
if $BLOCKED; then
|
|
55
|
+
echo "BLOCKED: Potential data exfiltration detected." >&2
|
|
56
|
+
echo " Reason: $REASON" >&2
|
|
57
|
+
echo " Command: $COMMAND" >&2
|
|
58
|
+
exit 2
|
|
59
|
+
fi
|
|
60
|
+
|
|
61
|
+
exit 0
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# TRIGGER: PreToolUse MATCHER: "Edit|Write"
|
|
2
4
|
CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
|
|
3
5
|
[ -z "$CONTENT" ] && exit 0
|
|
4
6
|
if echo "$CONTENT" | grep -qE "from ['\"]/|require\(['\"]/"; then echo "NOTE: Absolute import path detected" >&2; fi
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# TRIGGER: PreToolUse MATCHER: "Edit|Write"
|
|
2
4
|
CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
|
|
3
5
|
[ -z "$CONTENT" ] && exit 0
|
|
4
6
|
echo "$CONTENT" | grep -qE "\balert\(|\bconfirm\(|\bprompt\(" && echo "WARNING: alert/confirm/prompt in code" >&2
|
package/examples/no-any-type.sh
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# TRIGGER: PreToolUse MATCHER: "Edit|Write"
|
|
2
4
|
CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
|
|
3
5
|
[ -z "$CONTENT" ] && exit 0
|
|
4
6
|
echo "$CONTENT" | grep -qE ": any\b|<any>" && echo "NOTE: TypeScript any detected — add proper types" >&2
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# TRIGGER: PreToolUse MATCHER: "Edit|Write"
|
|
2
4
|
CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
|
|
3
5
|
[ -z "$CONTENT" ] && exit 0
|
|
4
6
|
echo "$CONTENT" | grep -qE "if\s*\([^=]*=[^=]" && echo "NOTE: Assignment in condition (use ===)" >&2
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# TRIGGER: PreToolUse MATCHER: "Edit|Write"
|
|
2
4
|
CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
|
|
3
5
|
[ -z "$CONTENT" ] && exit 0
|
|
4
6
|
DEPTH=$(echo "$CONTENT" | grep -c "function\s*("); [ "$DEPTH" -gt 3 ] && echo "NOTE: Possible callback hell ($DEPTH levels)" >&2
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# TRIGGER: PreToolUse MATCHER: "Edit|Write"
|
|
2
4
|
CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
|
|
3
5
|
[ -z "$CONTENT" ] && exit 0
|
|
4
6
|
echo "$CONTENT" | grep -qE "localStorage\.setItem.*password|sessionStorage.*token" && echo "WARNING: Storing secrets in browser storage" >&2
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# TRIGGER: PreToolUse MATCHER: "Edit|Write"
|
|
2
4
|
CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
|
|
3
5
|
[ -z "$CONTENT" ] && exit 0
|
|
4
6
|
COMMENTED=$(echo "$CONTENT" | grep -cE "^\s*(//|#)\s*(if|for|while|function|const|let|var|import|class)" || echo 0); [ "$COMMENTED" -gt 5 ] && echo "NOTE: Large block of commented code — delete or uncomment" >&2
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# TRIGGER: PreToolUse MATCHER: "Edit|Write"
|
|
2
4
|
CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
|
|
3
5
|
[ -z "$CONTENT" ] && exit 0
|
|
4
6
|
echo "$CONTENT" | grep -q "console.assert" && echo "NOTE: console.assert in code" >&2
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# TRIGGER: PermissionRequest MATCHER: ""
|
|
2
4
|
CONTENT=$(cat | jq -r '.tool_input.new_string // .tool_input.content // empty' 2>/dev/null)
|
|
3
5
|
[ -z "$CONTENT" ] && exit 0
|
|
4
6
|
if echo "$CONTENT" | grep -qE "catch\s*\([^)]*\)\s*\{[\s\n]*\}|except:[\s\n]*pass"; then echo "WARNING: Empty catch/except block swallows errors" >&2; fi
|