mcpField
B
block-no-verify-hook

block-no-verify-hook

github.com/wshobson安全41.9k6.7k 次安装2 周前更新
代码仓库

关于 block-no-verify-hook

block-no-verify-hook 是面向使用 AI 编码 Agent 团队的 Claude Code PreToolUse 钩子。它检查 Bash 调用,并在执行前拦截 Git 绕过标志,同时不影响其他工具调用。

主要功能

  1. 01拦截 Bash 工具调用
  2. 02阻止绕过 Git 钩子和签名的标志
  3. 03检查 JSON 输入中的命令文本
  4. 04通过退出码决定拦截或放行
  5. 05支持项目级或全局设置

适用场景

  1. 01防止提交时跳过 pre-commit 钩子
  2. 02对 Git 命令执行 GPG 签名要求
  3. 03阻止 Agent 使用短标志绕过检查

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/wshobson/agents --skill block-no-verify-hook

安装后在 Claude Code 中输入/block-no-verify-hook确认已加载。

详细介绍

阻止 --no-verify 钩子

PreToolUse 钩子配置,可在执行前拦截并阻止绕过标志的使用,确保 AI Agent 无法跳过 pre-commit 钩子、GPG 签名或其他 git 安全机制。

概述

AI 编码 Agent(Claude Code、Codex 等)可以使用 --no-verify 等标志运行 shell 命令,从而绕过 pre-commit 钩子。这会使 pre-commit 钩子中配置的 linting、格式化、测试和安全检查失去意义。block-no-verify 钩子添加了一个 PreToolUse 防护,在执行前拒绝任何包含绕过标志的工具调用。

问题

当 AI Agent 提交代码时,它们可能会使用绕过标志来避免钩子失败:

# These commands skip pre-commit hooks entirely
git commit --no-verify -m "quick fix"
git push --no-verify
git commit --no-gpg-sign -m "unsigned commit"
git merge --no-verify feature-branch

这会导致:

  • 未格式化的代码进入仓库
  • Linting 错误绕过检查
  • 安全扫描被跳过
  • 未签名提交绕过签名策略
  • 测试套件被规避

解决方案

在 .claude/settings.json 中添加一个 PreToolUse 钩子,用于检查每次 Bash 工具调用并阻止包含绕过标志的命令。

配置

将以下内容添加到项目的 .claude/settings.json:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "if grep -qE '\"command\"[[:space:]]*:[[:space:]]*\"([^\"\\\\]|\\\\.)*(--no-(ver|g)|commit([^\"\\\\]|\\\\.)*([[:space:]]|\\\\[tn])-[a-zA-Z]*n)'; then echo 'BLOCKED: --no-verify and --no-gpg-sign flags are not allowed. Run the commit without bypass flags so that pre-commit hooks execute properly.' >&2; exit 2; fi"
          }
        ]
      }
    ]
  }
}
工作原理
  1. 匹配器:该钩子仅针对 Bash 工具调用,因此不会干扰其他工具(Read、Edit、Grep 等)。
  2. 检查:Claude Code 通过 stdin 以 JSON 形式将工具调用发送给钩子,并且不会设置 $TOOL_INPUT 变量。该钩子使用 grep -E 搜索该 JSON 中的 command 值,因此不需要 jq 或 node,其他字段中的文本(例如 cwd 或工具调用的描述)也不会触发它。它会阻止 --no-verify、--no-gpg-sign 以及 git 接受的它们的任意较短前缀,例如 --no-veri。它还会阻止同一条命令中跟在 commit 之后、包含 n 的短选项组,例如 -n 或 -nm,因为 -n 是 --no-verify 的短形式。该钩子不会查找 git 这个词,因此它也能捕获 if git ...、sudo git ... 和 g=git; $g commit --no-verify。误匹配(例如提交信息中提到了某个标志)会阻止该调用,这是一种安全的失败方式。
  3. 阻止:如果在 git 命令中发现绕过标志,钩子会以代码 2 退出并打印错误消息。退出代码 2 会通知 Claude Code 完全拒绝该工具调用。
  4. 放行:如果未发现绕过标志,钩子会以代码 0 退出,命令将正常执行。
  5. 限制:该钩子检查的是文本,因此它可以阻止出于习惯而使用绕过标志的 Agent。它无法阻止刻意规避它的 Agent,例如通过拼接各部分来构造标志,或运行 git -c core.hooksPath=/dev/null commit。
退出代码
代码含义
0允许工具调用继续
1错误(工具调用仍会继续,并显示警告)
2完全阻止工具调用

被阻止的标志

标志用途为什么阻止
--no-verify跳过 pre-commit 和 commit-msg 钩子绕过 linting、格式化、测试、安全检查
--no-gpg-sign跳过 GPG 提交签名绕过提交签名策略

安装

按项目设置

在项目根目录创建或更新 .claude/settings.json:

mkdir -p .claude
cat > .claude/settings.json << 'EOF'
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "if grep -qE '\"command\"[[:space:]]*:[[:space:]]*\"([^\"\\\\]|\\\\.)*(--no-(ver|g)|commit([^\"\\\\]|\\\\.)*([[:space:]]|\\\\[tn])-[a-zA-Z]*n)'; then echo 'BLOCKED: --no-verify and --no-gpg-sign flags are not allowed. Run the commit without bypass flags so that pre-commit hooks execute properly.' >&2; exit 2; fi"
          }
        ]
      }
    ]
  }
}
EOF
全局设置

要在所有项目中强制执行,请添加到 ~/.claude/settings.json:

mkdir -p ~/.claude
cat > ~/.claude/settings.json << 'EOF'
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "if grep -qE '\"command\"[[:space:]]*:[[:space:]]*\"([^\"\\\\]|\\\\.)*(--no-(ver|g)|commit([^\"\\\\]|\\\\.)*([[:space:]]|\\\\[tn])-[a-zA-Z]*n)'; then echo 'BLOCKED: --no-verify and --no-gpg-sign flags are not allowed. Run the commit without bypass flags so that pre-commit hooks execute properly.' >&2; exit 2; fi"
          }
        ]
      }
    ]
  }
}
EOF

验证

测试该钩子会阻止绕过标志:

# This should be blocked by the hook:
git commit --no-verify -m "test"

# This should succeed normally:
git commit -m "test"

扩展钩子

添加更多被阻止的标志

要阻止其他标志(例如 --force),请扩展 grep 模式:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "if grep -qE '\"command\"[[:space:]]*:[[:space:]]*\"([^\"\\\\]|\\\\.)*(--no-(ver|g)|commit([^\"\\\\]|\\\\.)*([[:space:]]|\\\\[tn])-[a-zA-Z]*n|git([[:space:]]|\\\\t)([^\"\\\\]|\\\\.)*--force)'; then echo 'BLOCKED: Bypass flags are not allowed.' >&2; exit 2; fi"
          }
        ]
      }
    ]
  }
}
与其他钩子组合使用

block-no-verify 钩子可与其他 PreToolUse 钩子一起使用:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "if grep -qE '\"command\"[[:space:]]*:[[:space:]]*\"([^\"\\\\]|\\\\.)*(--no-(ver|g)|commit([^\"\\\\]|\\\\.)*([[:space:]]|\\\\[tn])-[a-zA-Z]*n)'; then echo 'BLOCKED: Bypass flags not allowed.' >&2; exit 2; fi"
          }
        ]
      },
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "if grep -qE 'rm[[:space:]]+-rf[[:space:]]+/'; then echo 'BLOCKED: Dangerous rm command.' >&2; exit 2; fi"
          }
        ]
      }
    ]
  }
}

最佳实践

  1. 提交设置文件 -- 将 .claude/settings.json 纳入版本控制,让所有团队成员都能受益于该 hook。
  2. 在入门文档中说明 -- 在项目的贡献指南中提及该 hook,让开发者理解为什么绕过标志会被阻止。
  3. 与 pre-commit hook 配合使用 -- block-no-verify hook 会确保 pre-commit hook 运行;请确保你配置了有实际作用的 pre-commit hook。
  4. 设置后进行测试 -- 在一次测试提交中有意触发该 hook,以验证其正常工作。

评论

支持 Markdown