Skip to content

原文(日本語に翻訳)

JSON を標準出力に出力して終了コード 2 で終了する PreToolUse フックが、ツール呼び出しを正しくブロックしない問題を修正

原文(英語)

Fixed PreToolUse hooks that emit JSON to stdout and exit with code 2 not correctly blocking the tool call

概要

PreToolUse フックで終了コード 2 を使用してツール呼び出しをブロックしようとした際に、フックが JSON を標準出力に書き込んでいると正しくブロックが機能しないバグが修正されました。フックによるツール呼び出しのブロックは、セキュリティポリシーの適用や危険な操作の防止に使用される重要な機能であり、この修正により信頼性が向上しました。

基本的な使い方

PreToolUse フックで終了コード 2 を使用したブロック:

bash
#!/bin/bash
# 危険なコマンドをブロックするフックの例
TOOL_INPUT=$(cat)

# JSONで入力を解析
COMMAND=$(echo "$TOOL_INPUT" | jq -r '.command // empty')

if echo "$COMMAND" | grep -qE "^(rm -rf|dd if=|mkfs)"; then
  # ブロック理由をJSONで出力
  echo '{"reason": "危険なコマンドはブロックされました", "blocked": true}'
  exit 2  # v2.1.90以降は正しくブロックされる
fi

exit 0

実践例

セキュリティポリシーの適用

本番環境への直接デプロイをブロックするフック:

bash
#!/bin/bash
TOOL_INPUT=$(cat)

# デプロイコマンドの検出
if echo "$TOOL_INPUT" | jq -e '.command | test("deploy.*production")' > /dev/null 2>&1; then
  echo '{
    "reason": "本番環境へのデプロイは承認が必要です",
    "action": "blocked",
    "contact": "devops@company.com"
  }'
  exit 2
fi

exit 0

設定への追加方法:

json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "/path/to/security-check.sh"
          }
        ]
      }
    ]
  }
}

ファイル変更の検証

特定のディレクトリへの変更をブロックするフック:

bash
#!/bin/bash
TOOL_INPUT=$(cat)

FILE_PATH=$(echo "$TOOL_INPUT" | jq -r '.file_path // empty')

if [[ "$FILE_PATH" == /etc/* ]] || [[ "$FILE_PATH" == /usr/* ]]; then
  echo '{"reason": "システムディレクトリへの変更は許可されていません"}'
  exit 2  # 修正後、正しくブロックされる
fi

exit 0

ツール呼び出しのロギングとブロック

監査ログ付きブロック:

bash
#!/bin/bash
TOOL_INPUT=$(cat)
TIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%SZ)

# 監査ログに記録
echo "{\"timestamp\": \"$TIMESTAMP\", \"input\": $TOOL_INPUT}" >> /var/log/claude-audit.log

# 特定のパターンをブロック
if echo "$TOOL_INPUT" | jq -e '.command | test("curl.*external-api")' > /dev/null 2>&1; then
  echo '{"reason": "外部APIへの直接アクセスはブロックされました", "logged": true}'
  exit 2
fi

exit 0

注意点

  • exit 2 はツール呼び出しをブロックするための終了コードです(exit 1 は別の動作)
  • JSON を標準出力に出力する場合は、有効な JSON 形式であることを確認してください
  • このバグは JSON を出力しながら exit 2 を使用する場合のみ影響していました
  • v2.1.90 以降では、JSON 出力の有無に関わらず exit 2 でのブロックが確実に機能します

関連情報