Skip to content

原文(日本語に翻訳)

フックのif条件フィルタリングが複合コマンド(ls && git push)や環境変数プレフィックス付きコマンド(FOO=bar git push)にマッチしない問題を修正しました。

原文(英語)

Fixed hooks if condition filtering not matching compound commands (ls && git push) or commands with env-var prefixes (FOO=bar git push)

概要

Claude Codeのフック機能における if 条件フィルタリングに問題がありました。&& で繋いだ複合コマンド(例: ls && git push)や、環境変数をプレフィックスとして指定したコマンド(例: FOO=bar git push)を実行する際に、フックの if 条件が正しくマッチされず、本来発火すべきフックが実行されませんでした。v2.1.89でコマンドパターンのマッチング処理が改善されました。

基本的な使い方

json
// .claude/settings.json でのフック設定例
{
  "hooks": {
    "PreToolUse": [
      {
        "type": "command",
        "command": "echo '危険なコマンドが検出されました'",
        "if": "tool == 'Bash' && (input.command contains 'git push')"
      }
    ]
  }
}

実践例

複合コマンドのフィルタリング

json
// 複合コマンドにマッチするフック設定
{
  "hooks": {
    "PreToolUse": [
      {
        "type": "command",
        "command": "bash /path/to/check-git-push.sh",
        "if": "tool == 'Bash'",
        "tools": ["Bash"]
      }
    ]
  }
}
bash
# check-git-push.sh の例
#!/bin/bash
# CLAUDE_TOOL_INPUT_COMMAND 環境変数でコマンドを確認
COMMAND="$CLAUDE_TOOL_INPUT_COMMAND"

# 修正前: "ls && git push" のような複合コマンドは検出できなかった
# 修正後: 正しく検出できる
if echo "$COMMAND" | grep -q "git push"; then
  echo "Warning: git push detected in command"
  # 承認を求めるなどの処理
fi

環境変数プレフィックス付きコマンドのフィルタリング

bash
# 修正前: "NODE_ENV=production npm run deploy" のようなコマンドで
# git push 関連のフックが発火しなかった

# 修正後: 環境変数プレフィックスを正しく処理してマッチする
# "FOO=bar git push origin main" のようなコマンドでも正しくフックが発火する

実際のセキュリティフック例

json
{
  "hooks": {
    "PreToolUse": [
      {
        "type": "command",
        "command": "python3 /home/user/.claude/hooks/check-dangerous-commands.py",
        "tools": ["Bash"]
      }
    ]
  }
}
python
#!/usr/bin/env python3
# check-dangerous-commands.py
import json
import sys
import re

tool_input = json.load(sys.stdin)
command = tool_input.get("command", "")

# コマンドを正規化(環境変数プレフィックスを除去)
normalized = re.sub(r'^(\w+=\S+\s+)+', '', command)

# 複合コマンドを分割して各部分をチェック
parts = re.split(r'\s*(?:&&|\|\||\|)\s*', normalized)

dangerous_patterns = ['rm -rf', 'git push --force', 'drop table']
for part in parts:
    for pattern in dangerous_patterns:
        if pattern in part:
            print(f"Dangerous command detected: {pattern}", file=sys.stderr)
            sys.exit(1)  # フックを拒否

注意点

  • if 条件での文字列マッチングは修正前から動作していましたが、複合コマンドと環境変数プレフィックスのケースが考慮されていませんでした
  • &&||| などで繋がれた複合コマンドは各パーツがチェックされます
  • VAR=value command 形式の環境変数プレフィックスは、実際のコマンドとして正しく認識されます
  • フックのデバッグには claude --debug モードが役立ちます

関連情報