1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Claude CodeのPreToolUseフックで危険な操作を自動ブロックする

1
Last updated at Posted at 2026-02-12

Zenn記事5本が消えた日

Claude Codeに「Zennの記事にフッターを追加して」と頼んだ。

エージェントはZenn APIに PUT を送った。フッターのテキストだけを。RESTの PUT はリソース全体を置き換える。本文がフッター1行に上書きされた。

教訓を書いた。「PUTの前に必ずGETせよ」と。

翌日。同じエージェントが同じミスをやった。今度は5記事全部。読者のコメントで気づいた。

教訓は書いてあった。読まれなかった。

教訓を「書く」だけでは意味がない

AIエージェントは忘れる。正確には、前のセッションの教訓を参照しない。CLAUDE.mdに書いても、長くなれば埋もれる。

必要なのは「教訓を書く仕組み」ではなく「教訓を守らせる仕組み」。

PreToolUseフックとは

:::details 初心者向け: フック(hook)とは
プログラムの「ある動作の前後に、自分のコードを差し込む仕組み」です。身近な例えで言うと、玄関のセンサーライトのようなもの。ドアが開く(=ツールが実行される)前にセンサーが反応して、ライトが点く(=チェックが走る)。PreToolUseフックは「ツール実行の前に差し込むチェック」で、危険な操作を事前にブロックできます。
:::

Claude Codeには hooks という仕組みがある。ツール実行の前後にコマンドを挟める。

  • PreToolUse — ツール実行に発火
  • PostToolUse — ツール実行に発火

PreToolUse フックがゼロ以外の終了コードを返すと、ツール実行がブロックされる。

ここに「過去の教訓との照合」を挟む。それがbrain guardの発想。

brain guardの仕組み

Shared BrainというCLIツールを作った。中核は brain guard コマンド。

処理の流れはこう。

コマンド文字列を受け取る
  ↓
全教訓ファイル(YAML)を読み込む
  ↓
各教訓の trigger_patterns と正規表現マッチ
  ↓
マッチあり → 警告表示 + チェックリスト提示 + 監査ログ記録
マッチなし → そのまま通過(監査ログには記録)

:::details 初心者向け: 正規表現(regex)とは
文字列のパターンを表現する記法です。たとえば curl.*PUT は「curlという文字の後ろのどこかにPUTがある文字列」にマッチします。.* は「何でもいい文字が0個以上」という意味。スマホの検索で * をワイルドカードとして使うのに似ています。brain guardでは、この正規表現でコマンドが危険かどうかを判定しています。
:::

実行例。

$ brain guard "curl -X PUT https://api.zenn.dev/articles/abc123"

============================================================
⚠️  CRITICAL LESSON: api-put-safety
   (violated 2x, last: 2026-02-09)
============================================================
   PUT replaces the ENTIRE resource. Fields not included in the
   request body will be overwritten with empty/default values.

   Checklist:
   [ ] GET the current resource state
   [ ] PUT body contains ALL required fields
   [ ] Test on 1 item before batch operation
   [ ] Verify result after update

   Source: Zenn 5-article deletion (2026-02-09)

Proceed? [y/N]

2回事故を起こした教訓が、3回目の前に割り込む。

設定方法

1. インストール

pip install shared-brain

または直接クローン。

git clone https://github.com/yurukusa/shared-brain.git
cd shared-brain
pip install -e .

2. Claude Codeへのフック登録

ワンコマンドで完了。

brain hook install

内部では ~/.claude/settings.json にこう書き込む。

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "/path/to/brain guard \"$TOOL_INPUT\""
          }
        ]
      }
    ]
  }
}

$TOOL_INPUT にはClaude Codeが実行しようとしているコマンド文字列が入る。brain guardはそれを受け取り、教訓データベースと照合する。

:::details 初心者向け: settings.jsonとは
Claude Codeの設定ファイルです。~/.claude/settings.json に置かれていて、ここにフックの定義を書くとClaude Codeが自動的に読み込みます。上のJSONの "matcher": "Bash" は「Bashコマンドを実行するときだけこのフックを発火させる」という意味です。
:::

既存の settings.json がある場合はマージ。既にインストール済みなら二重登録しない。冪等性あり。

# 確認
brain hook status
# 🟢 Installed

# 削除
brain hook uninstall

3. 教訓ファイルの書き方

教訓はYAML形式。~/.brain/lessons/ に置く。

# ~/.brain/lessons/api-put-safety.yaml
id: api-put-safety
severity: critical
created: "2026-02-08"
violated_count: 2
last_violated: "2026-02-09"

trigger_patterns:
  - "PUT /api/"
  - "requests\\.put"
  - "curl.*-X PUT"
  - "fetch.*method.*PUT"
  - "\\.put\\("
  - "PUT https?://"

lesson: |
  REST PUT replaces the ENTIRE resource. Fields not included in the
  request body will be overwritten with empty/default values.

  ALWAYS:
  1. GET the current resource state first
  2. Modify only the fields you need in the response data
  3. Send ALL fields in the PUT body
  4. Test on 1 item before batch operations
  5. Verify the result after the PUT

checklist:
  - "GET the current resource state"
  - "PUT body contains ALL required fields"
  - "Test on 1 item before batch operation"
  - "Verify result after update"

source:
  incident: "Zenn 5-article deletion (2026-02-09)"
  url: "https://zenn.dev/yurukusa/books/6076c23b1cb18b/viewer/2-safety-guards"

tags: [api, destructive, data-loss, rest]

各フィールドの役割。

フィールド 役割
id 教訓の一意識別子
severity critical / warning / info
trigger_patterns 正規表現のリスト。コマンド文字列と照合
lesson 教訓の本文。エージェントへの警告メッセージ
checklist 実行前に確認すべき項目
violated_count 過去の違反回数。重みづけの根拠
source 教訓の出典。なぜこの教訓が存在するか

4. 教訓の追加

ファイルから。

brain write -f my-lesson.yaml

対話式で。

brain write
# ID、severity、パターン、チェックリストを順に入力

もう一つ実例。git push --force を防ぐ教訓。

# ~/.brain/lessons/git-force-push.yaml
id: git-force-push
severity: critical
trigger_patterns:
  - "git push.*--force"
  - "git push.*-f "
  - "git reset --hard"
  - "git clean -fd"
  - "rm -rf"

lesson: |
  Force push, hard reset, and recursive delete are destructive
  operations that cannot be easily undone.

  Before any destructive git operation:
  1. Create a backup branch
  2. Verify you're on the correct branch
  3. Confirm the operation with the user

checklist:
  - "Created backup branch (git checkout -b backup/...)"
  - "Verified current branch is correct"
  - "User explicitly requested this destructive operation"

tags: [git, destructive, irreversible]

監査ログ

全てのguardチェックはJSONL形式で記録される。

{"timestamp": "2026-02-09T10:30:00+00:00", "agent": "cc-main", "action": "PUT /api/articles/abc", "lessons_matched": ["api-put-safety"], "checked": true, "followed": true, "note": "user_confirmed"}
{"timestamp": "2026-02-09T10:31:00+00:00", "agent": "cc-sub", "action": "curl -X PUT", "lessons_matched": ["api-put-safety"], "checked": true, "followed": false, "note": "user_aborted"}

brain audit で集計レポートが見える。

$ brain audit

📊 Audit Report
==================================================
Total checks: 47
Followed:     45
Blocked:      2
Compliance:   96%

Per-lesson breakdown:
  [api-put-safety] checks=12, followed=12, blocked=0
  [git-force-push] checks=5, followed=3, blocked=2

Last 10 entries:
  ✅ 2026-02-09T10:30 [cc-main] PUT /api/articles/abc (user_confirmed)
  ❌ 2026-02-09T10:31 [cc-sub] curl -X PUT (user_aborted)
  ...

「教訓を読んだか」「守ったか」が数値で出る。これが「教訓を書いただけ」との決定的な違い。

guard engineの実装

コアのパターンマッチ部分。約30行。

def guard(command: str, agent: str = "unknown", auto_confirm: bool = False) -> bool:
    """コマンドを全教訓と照合。安全ならTrue。"""
    lessons = load_all_lessons()
    matches = []

    for lesson in lessons:
        patterns = lesson.get("trigger_patterns", [])
        if not patterns:
            continue
        for pattern in patterns:
            try:
                if re.search(pattern, command, re.IGNORECASE):
                    matches.append(lesson)
                    break
            except re.error:
                # 正規表現が壊れていたら部分文字列マッチにフォールバック
                if pattern.lower() in command.lower():
                    matches.append(lesson)
                    break

    if not matches:
        log_audit(agent, command, None, checked=True, followed=True, note="no_match")
        return True

    # 警告表示 + チェックリスト提示
    for lesson in matches:
        display_warning(lesson)  # severity別の色分け表示

    # 監査ログ記録
    lesson_ids = [m.get("id", "unknown") for m in matches]
    log_audit(agent, command, lesson_ids, checked=True, followed=None, note="guard_triggered")

    return True  # 非インタラクティブ時は警告のみで通過

ポイント。

  • 正規表現マッチre.IGNORECASE で大文字小文字を無視
  • フォールバック。正規表現が不正でもクラッシュしない。部分文字列マッチに落ちる
  • 全件記録。マッチしなくても no_match として記録。「チェックが走ったこと自体」の証跡

PyYAMLなしでも動く

依存ライブラリはゼロ。PyYAMLがなくても自前の簡易YAMLパーサーで動作する。

try:
    import yaml
except ImportError:
    yaml = None  # フォールバックパーサーを使用

pip install を挟まずに即使える。CI環境やDocker内でも軽量に動く。

テスト

170テスト。全パス。0.98秒で完了。

$ python3 -m pytest tests/ -q
170 passed in 0.98s

カバー範囲。

  • YAMLパーサーのエッジケース(Unicode、空ファイル、壊れたYAML)
  • guardのパターンマッチ(複数マッチ、正規表現特殊文字、大文字小文字)
  • 監査ログ(1万件ロード、壊れたJSONL行のスキップ、同時書き込み)
  • hookのinstall/uninstall(冪等性、既存設定との共存)
  • Unicode全パイプライン(日本語教訓ID → guard発火 → 監査ログ → レポート表示)

組み込み教訓21種

最初から使える教訓を21個同梱している。一部を紹介。

教訓ID severity 何を防ぐか
api-put-safety critical GETなしPUTによるデータ上書き
git-force-push critical force push、hard reset、rm -rf
no-secrets-in-code critical コード内のAPIキー・パスワード
dont-delete-without-confirm warning 確認なしの削除操作
verify-before-claim warning 成功を確認せず「完了」と報告
test-before-deploy warning テストなしデプロイ
backup-before-migration warning バックアップなしのDB変更

自分のプロジェクト固有の教訓をYAMLで追加すれば、チーム全体で共有できる。

限界と注意点

過検知はある。 verify-before-claim の教訓は "successfully" や "completed" をトリガーにしている。普通のログ出力にも反応する。severity を info に下げるか、パターンを絞ることで対処する。

Claude Code固有。 PreToolUse フックはClaude Codeの機能。他のAIコーディングツールには直接使えない。ただし brain guard 自体はスタンドアロンのCLIなので、シェルエイリアスやgit hookとして他の環境でも使える。

# シェルエイリアスとして
alias curl='brain guard curl'

# git pre-commit hookとして
#!/bin/bash
brain guard "git commit" || exit 1

パターンの精度は使い手次第。 正規表現が甘いと誤検知する。厳しすぎると漏れる。実運用しながら調整するしかない。

教訓

AIエージェントに「気をつけて」と言っても無駄。仕組みで止める。

やったこと。

  1. 実際の事故(Zenn 5記事消失)から教訓をYAMLに構造化
  2. brain guard でコマンド実行前に自動照合
  3. Claude Codeの PreToolUse フックとして登録
  4. 監査ログで「読んだか・守ったか」を記録

教訓は書くものではなく、実行するものだ。


🛡️ npx cc-safe-setup — 650+個のhookをワンコマンドで導入
🔍 npx cc-health-check — 8カテゴリ・40+項目で環境をスコアリング
📘 Claude Codeを本番品質にする — 安全hookの設計から自律運用まで体系的に解説(¥800・Ch.2まで無料公開)
📖 AIに仕事を任せてみた — PreToolUseを含む658個のhookを作るまでの800時間の全記録(¥800・第2章まで無料)

リポジトリ: github.com/yurukusa/shared-brain

関連記事

設定が正しいか不安な方へ
無料で診断: npx cc-health-check で安全スコアを即座に確認できます。プロによる詳細レビュー($50〜)も受付中。

自分のトークン消費パターンを確認したい方へ
Token Checkupで5つの質問に答えるだけでトークン消費の診断ができる。Hook Selectorで最適なhookセットも分かる。


📖 トークン消費に困っているならClaude Codeのトークン消費を半分にする——800時間の運用データから見つけた実践テクニック(¥2,500・はじめに+第1章 無料)

📖 非エンジニアがClaude Codeで事業を回した全記録(¥800) — $800のAIコストで¥6,000を稼ぐまでの失敗と改善。第2章まで無料


⚠️ CVE-2026-21852(2026年4月公開): プロジェクト内.claude/settings.json経由でAPIキー窃盗。対策: npx cc-safe-setup(ユーザーレベル設定で免疫)→ 詳細

⚠️ Opus 4.7緊急情報(2026年4月17日)
Opus 4.7のauto mode安全分類器がOpus 4.6にハードコードされている問題が発覚。3日間で23件以上のデータ損失。さらにv2.1.100以降、APIコールごとに約20,000トークンが見えない場所で追加課金されている問題も判明(#46917、GitHub上196件のリアクション)(50GB永久消失含む)。4倍のトークン消費も報告されている。対策: npx cc-safe-setup --opus47Survival Guide / Safety Scanner

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?