Skip to content

guardrails: add block-dangerous-git guard (adapted, house parser) #285

Description

@kyle-sexton

Port evaluated and greenlit 2026-07-17 (capability from mattpocock/skills misc/git-guardrails-claude-code; implementation rejected — rewrite on our argv-grammar parser).

Scope: one new guard block-dangerous-git in the EXISTING guardrails plugin (PreToolUse on Bash), not a new plugin and not source-control (guardrails owns silent-always-on hooks).

Decisions from the evaluation:

  • Default block-list is irreversible-only: push --force/-f (not --force-with-lease), reset --hard, clean -f*, checkout ./restore ..
  • branch -D stays OUT of defaults: repo-hygiene's /clean issues inline git branch -D for squash-merged branches (verified collision), and it's reflog-recoverable.
  • Upstream's substring matching is defective (blocks ALL git push; checkout \. fires on checkout .github/...) — reuse the house tokenizer: lift parse_and_check/resolve_git_index from block-no-verify into lib/hook-utils.sh (SSOT via scripts/sync-hook-utils.sh) so both git guards share one parser.
  • Per-repo/per-user allow-list via env var (HOOK_BLOCK_DANGEROUS_GIT_ALLOW=...) in settings env, matching the plugin's HOOK_CLI_FLAG_VERIFY_BINS precedent. userConfig is structurally wrong here: project-level pluginConfigs are ignored since Claude Code 2.1.207.
  • Prompt-injection note: inline HOOK_..._ENABLED=false git push does NOT disable the hook (env prefix reaches only the git process). Residual risk = settings.json write access, the marketplace-wide hook trust boundary.

Scale: ~half day; new guard + .test.sh, hooks.json/README edits, guardrails 0.4.0 → 0.5.0. Hook plugins skip evals.

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions