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
package/COOKBOOK.md
CHANGED
|
@@ -236,6 +236,76 @@ npx cc-safe-setup --install-example push-requires-test-pass-record
|
|
|
236
236
|
|
|
237
237
|
Two-hook system: the PostToolUse `record` hook detects successful test runs (`npm test`, `pytest`, `cargo test`, etc.) and saves a timestamp. The PreToolUse hook blocks push to main/master/production if no recent test pass exists (30-minute window). See [#36673](https://github.com/anthropics/claude-code/issues/36673).
|
|
238
238
|
|
|
239
|
+
## Recipe: Protect CI/CD Pipelines
|
|
240
|
+
|
|
241
|
+
```bash
|
|
242
|
+
npx cc-safe-setup --install-example github-actions-secret-guard
|
|
243
|
+
npx cc-safe-setup --install-example ci-workflow-guard
|
|
244
|
+
npx cc-safe-setup --install-example gitops-drift-guard
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
Three-hook system: `github-actions-secret-guard` (PostToolUse) detects hardcoded secrets in workflow files. `ci-workflow-guard` (PostToolUse) flags `--no-verify`, remote script execution, and broad write permissions. `gitops-drift-guard` (PreToolUse) warns when editing infrastructure files on protected branches.
|
|
248
|
+
|
|
249
|
+
## Recipe: Kubernetes Production Safety
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
npx cc-safe-setup --install-example k8s-production-guard
|
|
253
|
+
# Set production contexts/namespaces:
|
|
254
|
+
export CC_K8S_PROD_CONTEXTS="prod:production"
|
|
255
|
+
export CC_K8S_PROD_NAMESPACES="production:prod"
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
Blocks `kubectl delete`, `scale --replicas=0`, `drain`, and `helm uninstall` on production namespaces/contexts. Safe operations (get, logs, describe) are always allowed.
|
|
259
|
+
|
|
260
|
+
## Recipe: MCP Server Allowlist
|
|
261
|
+
|
|
262
|
+
```bash
|
|
263
|
+
npx cc-safe-setup --install-example mcp-server-allowlist
|
|
264
|
+
npx cc-safe-setup --install-example mcp-tool-audit-log
|
|
265
|
+
export CC_MCP_ALLOWED="github:filesystem:memory"
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Only allows MCP tool calls from whitelisted servers. Blocks calls from unknown/synced servers that may cause OOM crashes ([#20412](https://github.com/anthropics/claude-code/issues/20412)). The audit log records all MCP tool calls for security review (OWASP MCP09 compliance).
|
|
269
|
+
|
|
270
|
+
## Recipe: Role-Based Agent Teams
|
|
271
|
+
|
|
272
|
+
```bash
|
|
273
|
+
npx cc-safe-setup --install-example role-tool-guard
|
|
274
|
+
echo "pm" > .claude/current-role.txt
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
Restricts tools based on agent role. PM can only read and delegate (no Edit/Write/Bash). Architect can design but not execute. Reviewer is read-only. Developer has full access. Switch roles: `echo "developer" > .claude/current-role.txt`. See [#40425](https://github.com/anthropics/claude-code/issues/40425).
|
|
278
|
+
|
|
279
|
+
## Recipe: Fix git show --no-stat Bug
|
|
280
|
+
|
|
281
|
+
Claude Code frequently runs `git show <ref> --no-stat`, which fails because `--no-stat` is not a valid git-show flag. This wastes context on error output. The hook silently rewrites the command.
|
|
282
|
+
|
|
283
|
+
```bash
|
|
284
|
+
npx cc-safe-setup --install-example git-show-flag-sanitizer
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
Install in `.claude/settings.json` as a PreToolUse hook with matcher `Bash`. The hook detects `git show` + `--no-stat`, strips the invalid flag, and returns the corrected command via `updatedInput`. See [#13071](https://github.com/anthropics/claude-code/issues/13071).
|
|
288
|
+
|
|
289
|
+
## Recipe: Disable Auto-Compaction
|
|
290
|
+
|
|
291
|
+
Power users who manage context manually can block auto-compaction entirely:
|
|
292
|
+
|
|
293
|
+
```bash
|
|
294
|
+
npx cc-safe-setup --install-example compact-blocker
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
Install as a PreCompact hook (no matcher needed). Exit code 2 blocks compaction. For conditional control, add a guard: `[ -f /tmp/allow-compact ] && exit 0`. See [#6689](https://github.com/anthropics/claude-code/issues/6689).
|
|
298
|
+
|
|
299
|
+
## Recipe: WebFetch Domain Allowlist
|
|
300
|
+
|
|
301
|
+
`WebFetch(domain:*)` in settings.json fails in sandbox mode. This hook auto-approves WebFetch requests by domain:
|
|
302
|
+
|
|
303
|
+
```bash
|
|
304
|
+
npx cc-safe-setup --install-example webfetch-domain-allow
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
Install as a PreToolUse hook with matcher `WebFetch`. By default allows all domains. Set `CC_WEBFETCH_ALLOW_DOMAINS=github.com,docs.anthropic.com` for specific domains. See [#9329](https://github.com/anthropics/claude-code/issues/9329).
|
|
308
|
+
|
|
239
309
|
## Further Reading
|
|
240
310
|
|
|
241
311
|
- [Getting Started](https://yurukusa.github.io/cc-safe-setup/getting-started.html)
|
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
[](https://www.npmjs.com/package/cc-safe-setup)
|
|
5
5
|
[](https://github.com/yurukusa/cc-safe-setup/actions/workflows/test.yml)
|
|
6
6
|
|
|
7
|
-
**One command to make Claude Code safe for autonomous operation.**
|
|
7
|
+
**One command to make Claude Code safe for autonomous operation.** 611 example hooks · 10,411 tests · 1,000+ installs/day · [日本語](docs/README.ja.md)
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
10
|
npx cc-safe-setup
|
|
@@ -91,6 +91,9 @@ Override Claude Code's built-in confirmation prompts. These run **after** the bu
|
|
|
91
91
|
| `edit-always-allow` | Edit prompts in `.claude/skills/` despite `bypassPermissions` | [#36192](https://github.com/anthropics/claude-code/issues/36192) |
|
|
92
92
|
| `allow-git-hooks-dir` | Edit prompts in `.git/hooks/` for pre-commit/pre-push setup | |
|
|
93
93
|
| `allow-protected-dirs` | All protected directory prompts (CI/Docker environments) | [#36168](https://github.com/anthropics/claude-code/issues/36168) |
|
|
94
|
+
| `git-show-flag-sanitizer` | Strips invalid `--no-stat` from `git show` (wastes context on error) | [#13071](https://github.com/anthropics/claude-code/issues/13071) |
|
|
95
|
+
| `compact-blocker` | Blocks auto-compaction via PreCompact (preserves full context) | [#6689](https://github.com/anthropics/claude-code/issues/6689) |
|
|
96
|
+
| `webfetch-domain-allow` | Auto-approves WebFetch by domain (fixes broken `domain:*` wildcard) | [#9329](https://github.com/anthropics/claude-code/issues/9329) |
|
|
94
97
|
|
|
95
98
|
Install any of these: `npx cc-safe-setup --install-example <name>`
|
|
96
99
|
|
|
@@ -117,7 +120,7 @@ Install any of these: `npx cc-safe-setup --install-example <name>`
|
|
|
117
120
|
| `--scan [--apply]` | Tech stack detection |
|
|
118
121
|
| `--export / --import` | Team config sharing |
|
|
119
122
|
| `--verify` | Test each hook |
|
|
120
|
-
| `--install-example <name>` | Install from
|
|
123
|
+
| `--install-example <name>` | Install from 564 examples |
|
|
121
124
|
| `--examples [filter]` | Browse examples by keyword |
|
|
122
125
|
| `--full` | All-in-one setup |
|
|
123
126
|
| `--status` | Check installed hooks |
|
|
@@ -404,6 +407,7 @@ See [Issue #1](https://github.com/yurukusa/cc-safe-setup/issues/1) for details.
|
|
|
404
407
|
- [Cookbook](COOKBOOK.md) — 26 practical recipes (block, approve, protect, monitor, diagnose)
|
|
405
408
|
- [Official Hooks Reference](https://code.claude.com/docs/en/hooks) — Claude Code hooks documentation
|
|
406
409
|
- [Hooks Cookbook](https://github.com/yurukusa/claude-code-hooks/blob/main/COOKBOOK.md) — 25 recipes from real GitHub Issues ([interactive version](https://yurukusa.github.io/claude-code-hooks/))
|
|
410
|
+
- [Skills Guide deep-dive (Qiita, 19K+ views)](https://qiita.com/yurukusa/items/f69920b4a02cf7e2988c) — Anthropic's official Skills PDF analyzed with 40% token reduction
|
|
407
411
|
- [Japanese guide (Qiita)](https://qiita.com/yurukusa/items/a9714b33f5d974e8f1e8) — この記事の日本語解説
|
|
408
412
|
- [v2.1.85 `if` field guide (Qiita)](https://qiita.com/yurukusa/items/7079866e9dc239fcdd57) — Reduce hook overhead with conditional execution
|
|
409
413
|
- [Hook Test Runner](https://github.com/yurukusa/cc-hook-test) — `npx cc-hook-test <hook.sh>` to auto-test any hook
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# absolute-rule-enforcer.sh — Enforce CLAUDE.md "ABSOLUTE RULE" markers
|
|
3
|
+
#
|
|
4
|
+
# Solves: ABSOLUTE RULEs in CLAUDE.md treated as advisory (#40284).
|
|
5
|
+
# Even rules marked with strong language get ignored under
|
|
6
|
+
# context pressure. This hook extracts and enforces them.
|
|
7
|
+
#
|
|
8
|
+
# How it works: Stop hook that parses CLAUDE.md for "ABSOLUTE RULE"
|
|
9
|
+
# or "MUST NEVER" markers, extracts the constraint keywords,
|
|
10
|
+
# and checks if the session violated them.
|
|
11
|
+
#
|
|
12
|
+
# TRIGGER: Stop
|
|
13
|
+
# MATCHER: ""
|
|
14
|
+
|
|
15
|
+
set -euo pipefail
|
|
16
|
+
|
|
17
|
+
# Find CLAUDE.md
|
|
18
|
+
CLAUDEMD=""
|
|
19
|
+
for candidate in "CLAUDE.md" "../CLAUDE.md" "../../CLAUDE.md"; do
|
|
20
|
+
if [ -f "$candidate" ]; then
|
|
21
|
+
CLAUDEMD="$candidate"
|
|
22
|
+
break
|
|
23
|
+
fi
|
|
24
|
+
done
|
|
25
|
+
|
|
26
|
+
[ -z "$CLAUDEMD" ] && exit 0
|
|
27
|
+
|
|
28
|
+
# Extract absolute rules (lines containing ABSOLUTE, MUST NEVER, NEVER, 絶対)
|
|
29
|
+
RULES=$(grep -iE '(ABSOLUTE|MUST NEVER|NEVER|絶対|禁止)' "$CLAUDEMD" 2>/dev/null | head -10 || true)
|
|
30
|
+
|
|
31
|
+
if [ -z "$RULES" ]; then
|
|
32
|
+
exit 0
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
# Log that absolute rules exist (reminder to model via stderr)
|
|
36
|
+
echo "REMINDER: This project has absolute rules in CLAUDE.md:" >&2
|
|
37
|
+
echo "$RULES" | head -5 | while IFS= read -r rule; do
|
|
38
|
+
echo " $rule" >&2
|
|
39
|
+
done
|
|
40
|
+
echo "Verify your changes comply before finalizing." >&2
|
|
41
|
+
|
|
42
|
+
exit 0
|
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
# WARNING: Only use in environments where you trust Claude's edits
|
|
14
14
|
# to your configuration. In shared or production environments,
|
|
15
15
|
# keep the default prompts.
|
|
16
|
+
#
|
|
17
|
+
# TRIGGER: PermissionRequest MATCHER: ""
|
|
16
18
|
|
|
17
19
|
INPUT=$(cat)
|
|
18
20
|
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
|
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
#
|
|
10
10
|
# WARNING: Only allow specific subdirectories you trust.
|
|
11
11
|
# Never blanket-allow all of .git/ — that exposes HEAD, config, etc.
|
|
12
|
+
#
|
|
13
|
+
# TRIGGER: PermissionRequest MATCHER: ""
|
|
12
14
|
|
|
13
15
|
INPUT=$(cat)
|
|
14
16
|
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
|
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
# It bypasses ALL built-in file protection. Do NOT use in shared or
|
|
14
14
|
# production environments. Prefer allow-git-hooks-dir.sh or
|
|
15
15
|
# allow-claude-settings.sh for targeted bypass.
|
|
16
|
+
#
|
|
17
|
+
# TRIGGER: PermissionRequest MATCHER: ""
|
|
16
18
|
|
|
17
19
|
INPUT=$(cat)
|
|
18
20
|
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
|
package/examples/allowlist.sh
CHANGED
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
#
|
|
15
15
|
# See: https://github.com/anthropics/claude-code/issues/30519
|
|
16
16
|
# See: https://github.com/anthropics/claude-code/issues/16561
|
|
17
|
+
#
|
|
18
|
+
# TRIGGER: PermissionRequest MATCHER: ""
|
|
17
19
|
|
|
18
20
|
INPUT=$(cat)
|
|
19
21
|
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
@@ -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*(npm\s+test|npm\s+run\s+test|npx\s+(jest|vitest|mocha|ava|tap|playwright\s+test|cypress\s+run)|yarn\s+test|pnpm\s+test|bun\s+test)\b'; then
|
|
@@ -13,13 +13,13 @@
|
|
|
13
13
|
# Default banned commands (configurable via CC_BANNED_COMMANDS):
|
|
14
14
|
# sed -i (in-place file editing — use Edit tool instead)
|
|
15
15
|
# awk -i inplace (same reason)
|
|
16
|
-
# perl -
|
|
16
|
+
# perl -i / perl -pi (same reason — covers -i -pe, -pi -e, etc.)
|
|
17
17
|
#
|
|
18
18
|
# TRIGGER: PreToolUse MATCHER: "Bash"
|
|
19
19
|
#
|
|
20
20
|
# Configuration:
|
|
21
21
|
# CC_BANNED_COMMANDS — colon-separated list of regex patterns to block
|
|
22
|
-
# Default: "sed -i:awk -i inplace:perl -pi"
|
|
22
|
+
# Default: "sed -i:awk -i inplace:perl -pi:perl .*-i"
|
|
23
23
|
|
|
24
24
|
INPUT=$(cat)
|
|
25
25
|
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
@@ -27,7 +27,7 @@ COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
|
27
27
|
[ -z "$COMMAND" ] && exit 0
|
|
28
28
|
|
|
29
29
|
# Configurable banned patterns (colon-separated)
|
|
30
|
-
BANNED="${CC_BANNED_COMMANDS:-sed\s+-i:awk\s+-i\s+inplace:perl\s+-pi}"
|
|
30
|
+
BANNED="${CC_BANNED_COMMANDS:-sed\s+-i:awk\s+-i\s+inplace:perl\s+-pi:perl\s+.*-i}"
|
|
31
31
|
|
|
32
32
|
# Check each banned pattern
|
|
33
33
|
IFS=':' read -ra PATTERNS <<< "$BANNED"
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# bash-domain-allowlist.sh — Block curl/wget to unauthorized domains
|
|
3
|
+
#
|
|
4
|
+
# Solves: Sandbox allowedDomains not enforced for plain HTTP requests,
|
|
5
|
+
# allowing data exfiltration via curl/wget (#40213).
|
|
6
|
+
# Also provides defense-in-depth when sandbox is not available.
|
|
7
|
+
#
|
|
8
|
+
# How it works: PreToolUse hook on Bash that extracts target domains from
|
|
9
|
+
# curl/wget commands and blocks requests to domains not in the allowlist.
|
|
10
|
+
#
|
|
11
|
+
# TRIGGER: PreToolUse
|
|
12
|
+
# MATCHER: "Bash"
|
|
13
|
+
#
|
|
14
|
+
# Usage:
|
|
15
|
+
# {
|
|
16
|
+
# "hooks": {
|
|
17
|
+
# "PreToolUse": [{
|
|
18
|
+
# "matcher": "Bash",
|
|
19
|
+
# "hooks": [{ "type": "command", "command": "~/.claude/hooks/bash-domain-allowlist.sh" }]
|
|
20
|
+
# }]
|
|
21
|
+
# }
|
|
22
|
+
# }
|
|
23
|
+
#
|
|
24
|
+
# Configuration: Set CC_ALLOWED_DOMAINS env var (comma-separated)
|
|
25
|
+
# or edit the ALLOWED_DOMAINS array below.
|
|
26
|
+
|
|
27
|
+
INPUT=$(cat)
|
|
28
|
+
CMD=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
|
|
29
|
+
[ -z "$CMD" ] && exit 0
|
|
30
|
+
|
|
31
|
+
# Only check commands that make HTTP requests
|
|
32
|
+
echo "$CMD" | grep -qE '\b(curl|wget|http|fetch)\b' || exit 0
|
|
33
|
+
|
|
34
|
+
# ========================================
|
|
35
|
+
# DOMAIN ALLOWLIST — edit to your needs
|
|
36
|
+
# ========================================
|
|
37
|
+
if [ -n "$CC_ALLOWED_DOMAINS" ]; then
|
|
38
|
+
IFS=',' read -ra ALLOWED_DOMAINS <<< "$CC_ALLOWED_DOMAINS"
|
|
39
|
+
else
|
|
40
|
+
ALLOWED_DOMAINS=(
|
|
41
|
+
"github.com"
|
|
42
|
+
"api.github.com"
|
|
43
|
+
"raw.githubusercontent.com"
|
|
44
|
+
"registry.npmjs.org"
|
|
45
|
+
"pypi.org"
|
|
46
|
+
"*.amazonaws.com"
|
|
47
|
+
"localhost"
|
|
48
|
+
"127.0.0.1"
|
|
49
|
+
)
|
|
50
|
+
fi
|
|
51
|
+
|
|
52
|
+
# Extract target domains from URLs in the command
|
|
53
|
+
DOMAINS=$(echo "$CMD" | grep -oE 'https?://[^/"'"'"'"'"'"' ]+' | sed -E 's|^https?://||;s|/.*||;s|:.*||' | sort -u)
|
|
54
|
+
[ -z "$DOMAINS" ] && exit 0
|
|
55
|
+
|
|
56
|
+
for domain in $DOMAINS; do
|
|
57
|
+
allowed=false
|
|
58
|
+
for pattern in "${ALLOWED_DOMAINS[@]}"; do
|
|
59
|
+
# Convert glob to regex (*.example.com -> .*\.example\.com)
|
|
60
|
+
regex=$(echo "$pattern" | sed 's/\./\\./g; s/\*/.*/g')
|
|
61
|
+
if echo "$domain" | grep -qE "^${regex}$"; then
|
|
62
|
+
allowed=true
|
|
63
|
+
break
|
|
64
|
+
fi
|
|
65
|
+
done
|
|
66
|
+
if [ "$allowed" = false ]; then
|
|
67
|
+
echo "BLOCKED: HTTP request to unauthorized domain: $domain" >&2
|
|
68
|
+
echo "Allowed: ${ALLOWED_DOMAINS[*]}" >&2
|
|
69
|
+
exit 2
|
|
70
|
+
fi
|
|
71
|
+
done
|
|
72
|
+
exit 0
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# bash-safety-auto-deny.sh — Auto-deny commands that trigger safety prompts
|
|
3
|
+
#
|
|
4
|
+
# Solves: Users want "auto-deny" instead of "prompt" for risky commands (#28993).
|
|
5
|
+
# Currently Claude's safety heuristic prompts the user. This hook
|
|
6
|
+
# blocks the command outright, forcing Claude to reformulate.
|
|
7
|
+
#
|
|
8
|
+
# How it works: PreToolUse hook on Bash that detects patterns the built-in
|
|
9
|
+
# safety system would flag, and blocks them with exit 2 instead of
|
|
10
|
+
# prompting. Claude learns to use safer alternatives.
|
|
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
|
+
# Patterns that trigger built-in safety prompts
|
|
22
|
+
# 1. Pipe to bash/sh (command injection risk)
|
|
23
|
+
if echo "$COMMAND" | grep -qE '\|\s*(bash|sh|zsh)\b'; then
|
|
24
|
+
echo "BLOCKED: Piping to shell interpreter detected." >&2
|
|
25
|
+
echo "Reformulate without piping to bash/sh." >&2
|
|
26
|
+
exit 2
|
|
27
|
+
fi
|
|
28
|
+
|
|
29
|
+
# 2. curl/wget piped to execution
|
|
30
|
+
if echo "$COMMAND" | grep -qE '(curl|wget)\s.*\|\s*(bash|sh|python|node|perl)'; then
|
|
31
|
+
echo "BLOCKED: Remote code execution pattern detected." >&2
|
|
32
|
+
echo "Download the file first, review it, then execute separately." >&2
|
|
33
|
+
exit 2
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
# 3. eval with variable expansion
|
|
37
|
+
if echo "$COMMAND" | grep -qE '\beval\s'; then
|
|
38
|
+
echo "BLOCKED: eval detected. Use direct commands instead." >&2
|
|
39
|
+
exit 2
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
# 4. Nested command substitution in dangerous positions
|
|
43
|
+
if echo "$COMMAND" | grep -qE '(rm|mv|cp|chmod|chown)\s.*\$\('; then
|
|
44
|
+
echo "BLOCKED: Command substitution in destructive command." >&2
|
|
45
|
+
echo "Expand the subcommand first, verify the result, then run." >&2
|
|
46
|
+
exit 2
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
# 5. Globbed rm (rm *.* or rm -rf *)
|
|
50
|
+
if echo "$COMMAND" | grep -qE 'rm\s+.*\*'; then
|
|
51
|
+
echo "BLOCKED: Wildcard deletion detected." >&2
|
|
52
|
+
echo "List the files first (ls), verify, then delete specific files." >&2
|
|
53
|
+
exit 2
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
exit 0
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# bash-secret-output-detector.sh — Warn when Bash output contains secrets
|
|
3
|
+
#
|
|
4
|
+
# Solves: Bash command output containing API keys, tokens, or credentials
|
|
5
|
+
# enters the LLM context window and gets sent to the API provider
|
|
6
|
+
# (#39882). PostToolUse hook that scans stdout for secret patterns.
|
|
7
|
+
#
|
|
8
|
+
# How it works: PostToolUse hook on Bash that checks command stdout for
|
|
9
|
+
# patterns matching API keys, tokens, passwords, and connection strings.
|
|
10
|
+
# Emits a systemMessage warning the model to ignore/not repeat secrets.
|
|
11
|
+
#
|
|
12
|
+
# TRIGGER: PostToolUse
|
|
13
|
+
# MATCHER: "Bash"
|
|
14
|
+
#
|
|
15
|
+
# Usage:
|
|
16
|
+
# {
|
|
17
|
+
# "hooks": {
|
|
18
|
+
# "PostToolUse": [{
|
|
19
|
+
# "matcher": "Bash",
|
|
20
|
+
# "hooks": [{ "type": "command", "command": "~/.claude/hooks/bash-secret-output-detector.sh" }]
|
|
21
|
+
# }]
|
|
22
|
+
# }
|
|
23
|
+
# }
|
|
24
|
+
|
|
25
|
+
INPUT=$(cat)
|
|
26
|
+
STDOUT=$(echo "$INPUT" | jq -r '.tool_result.stdout // empty' 2>/dev/null)
|
|
27
|
+
|
|
28
|
+
[ -z "$STDOUT" ] && exit 0
|
|
29
|
+
|
|
30
|
+
# Secret patterns (high-confidence, low false-positive)
|
|
31
|
+
FOUND=""
|
|
32
|
+
|
|
33
|
+
# AWS keys
|
|
34
|
+
if echo "$STDOUT" | grep -qE 'AKIA[0-9A-Z]{16}'; then
|
|
35
|
+
FOUND="${FOUND}AWS access key, "
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
# Generic API keys/tokens (long hex/base64 strings after key= or token=)
|
|
39
|
+
if echo "$STDOUT" | grep -qiE '(api[_-]?key|api[_-]?secret|auth[_-]?token|access[_-]?token|secret[_-]?key)\s*[:=]\s*\S{20,}'; then
|
|
40
|
+
FOUND="${FOUND}API key/token, "
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
# Connection strings with passwords
|
|
44
|
+
if echo "$STDOUT" | grep -qiE '(mysql|postgres|mongodb|redis)://[^:]+:[^@]+@'; then
|
|
45
|
+
FOUND="${FOUND}database connection string, "
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
# Private keys
|
|
49
|
+
if echo "$STDOUT" | grep -qE '-----BEGIN (RSA |EC |OPENSSH )?PRIVATE KEY-----'; then
|
|
50
|
+
FOUND="${FOUND}private key, "
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
# JWT tokens
|
|
54
|
+
if echo "$STDOUT" | grep -qE 'eyJ[A-Za-z0-9_-]{10,}\.eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]+'; then
|
|
55
|
+
FOUND="${FOUND}JWT token, "
|
|
56
|
+
fi
|
|
57
|
+
|
|
58
|
+
# GitHub/GitLab tokens
|
|
59
|
+
if echo "$STDOUT" | grep -qE '(ghp|gho|ghs|ghr|glpat)_[A-Za-z0-9]{30,}'; then
|
|
60
|
+
FOUND="${FOUND}GitHub/GitLab token, "
|
|
61
|
+
fi
|
|
62
|
+
|
|
63
|
+
if [ -n "$FOUND" ]; then
|
|
64
|
+
FOUND="${FOUND%, }"
|
|
65
|
+
echo "{\"systemMessage\":\"⚠ SECRET DETECTED in command output: ${FOUND}. Do NOT repeat, log, or include these values in any output. They are now in context but should be treated as redacted.\"}"
|
|
66
|
+
fi
|
|
67
|
+
|
|
68
|
+
exit 0
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# bashrc-safety-check.sh — Warn about .bashrc lines that hang in non-interactive shells
|
|
3
|
+
#
|
|
4
|
+
# Solves: Agent-spawned bash shells source user .bashrc/.bash_profile,
|
|
5
|
+
# causing hangs or process cascades when completion scripts or
|
|
6
|
+
# slow init commands run in non-interactive shells (#40354).
|
|
7
|
+
#
|
|
8
|
+
# How it works: SessionStart hook scans .bashrc for known-dangerous patterns
|
|
9
|
+
# (completion scripts, nvm, conda, pyenv) and warns the user to add an
|
|
10
|
+
# interactive-shell guard.
|
|
11
|
+
#
|
|
12
|
+
# TRIGGER: SessionStart
|
|
13
|
+
# MATCHER: ""
|
|
14
|
+
#
|
|
15
|
+
# Usage:
|
|
16
|
+
# {
|
|
17
|
+
# "hooks": {
|
|
18
|
+
# "SessionStart": [{
|
|
19
|
+
# "hooks": [{ "type": "command", "command": "~/.claude/hooks/bashrc-safety-check.sh" }]
|
|
20
|
+
# }]
|
|
21
|
+
# }
|
|
22
|
+
# }
|
|
23
|
+
|
|
24
|
+
BASHRC="$HOME/.bashrc"
|
|
25
|
+
[ ! -f "$BASHRC" ] && exit 0
|
|
26
|
+
|
|
27
|
+
# Check if .bashrc already has a non-interactive guard at the top
|
|
28
|
+
if head -10 "$BASHRC" | grep -qE 'case \$- in|\[\[ \$- ==.*i'; then
|
|
29
|
+
# Already guarded — skip check
|
|
30
|
+
exit 0
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
# Patterns known to hang/crash in non-interactive agent shells
|
|
34
|
+
DANGEROUS_PATTERNS=(
|
|
35
|
+
'source.*<.*completion' # Angular CLI, kubectl, etc.
|
|
36
|
+
'eval.*\$.*completion' # Completion eval patterns
|
|
37
|
+
'nvm\.sh' # nvm can be slow on init
|
|
38
|
+
'conda.*activate' # conda activation in non-interactive
|
|
39
|
+
'pyenv.*init' # pyenv init sometimes hangs
|
|
40
|
+
'rbenv.*init' # rbenv init
|
|
41
|
+
'rvm.*scripts' # rvm scripts
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
WARNINGS=""
|
|
45
|
+
for pattern in "${DANGEROUS_PATTERNS[@]}"; do
|
|
46
|
+
MATCH=$(grep -n "$pattern" "$BASHRC" 2>/dev/null | head -3)
|
|
47
|
+
if [ -n "$MATCH" ]; then
|
|
48
|
+
WARNINGS="${WARNINGS}\n Line: $MATCH"
|
|
49
|
+
fi
|
|
50
|
+
done
|
|
51
|
+
|
|
52
|
+
if [ -n "$WARNINGS" ]; then
|
|
53
|
+
echo "⚠ WARNING: .bashrc contains commands that may hang in agent subshells:" >&2
|
|
54
|
+
echo -e "$WARNINGS" >&2
|
|
55
|
+
echo "" >&2
|
|
56
|
+
echo "Add this as the FIRST line of .bashrc to fix:" >&2
|
|
57
|
+
echo ' case $- in *i*) ;; *) return;; esac' >&2
|
|
58
|
+
fi
|
|
59
|
+
exit 0
|