Bible Network Crypto DeFi Onchain RWA AI Agent Stablecoin Chain SAFU CryptoTax DeFAI AGI Claude Me Claude Skill Claude Design Claude Cowork
独立メディア
いかなるプロジェクトとも無提携
Claudeスキルを学んで、すべてをもっとうまくやろう
claudeskill-me.com
最新
Claude Code 2.1.299へ上げる前に確認:MCP allowルールの厳格化、名前に妙な文字を含むスキルの除外、UserPromptSubmitフックの実行順の変更  ·  Claude Codeにアイドル圧縮が追加:200Kトークン超の会話は約54分の放置で自動圧縮——節約できるのはキャッシュ費用、失うのは細部かもしれない  ·  forkサブエージェントは空白から始めず会話全体を引き継ぐ——v2.1.302からVS Code、デスクトップ、ヘッドレスでも既定で有効に  ·  claude plugin evalの仕組み:「入れた場合/入れない場合」の差Δでスキルの効果を測る——そしてΔがCIを落とさない理由  ·  Claude Codeのフックは既定でfail-open:スクリプト不在、タイムアウト、exit 1でも通過する——v2.1.295のonFailure: "block"の使い方  ·  Claude Haiku 5.5がClaude Codeの既定Haikuに:入力は$0.10まで下がるが、100Kトークンを超えるとリクエスト全体が5倍になる
practice

Claude Codeのフックは既定でfail-open:スクリプト不在、タイムアウト、exit 1でも通過する——v2.1.295のonFailure: "block"の使い方

30秒バージョン · 忙しい方へ
フックのexit 2は門番の判決だが、門番がそもそも出勤していなければ、既定の結果は通過だ。

詳しく読む +
01 · なぜ起きたのか?

exit 2を返すPreToolUseフックはすでにあります。onFailureはまだ必要ですか?

検討する価値がある。exit 2が効くのは、スクリプトが実際に動き、意図的に2を返したときだけだ。パスの打ち間違い、実行権限の欠如、タイムアウト、スクリプトが途中で落ちて1で終わる場合、ガードは何も「判決」を下しておらず、既定は通過になる。onFailure: "block"はまさに「門番が出勤していない」ケースを補うので、両者は補い合う関係だ。

02 · 仕組みは?

自分のフックが本当にfail-closedになっているか、どう確かめますか?

使い捨てのディレクトリでclaude -pを使い、小さく試す。3つを別々に行う。スクリプトのパスをわざと誤る、スクリプトにsleepを入れてタイムアウトを超えさせる、スクリプトをそのままexit 1させる。それぞれで、本来ブロックされるはずの無害なコマンドをClaudeに実行させ、ブロックされることを確認する。その後設定を戻して、安全なコマンドが通ることも確認する。Developers Digestの検証もこの考え方で、フックだけを変数にしている。

03 · 自分にどう影響する?

promptフックやagentフックでもonFailureは使えますか?

Developers Digestの整理によれば、現時点では対象外だ。onFailureはcommandとHTTPのフックにだけ適用される。確実に止めたいルールは、commandフックを門番にして前述のようにfail-closedにするのがよい。promptフックとagentフックは、意味的な判断が必要なゆるい検査に向いている。v2.1.294も、指示文として書かれたこの2種類が以前は止めるべきものを通していたと述べており、唯一の防衛線には向かないことがわかる。

04 · どうすればいい?

エンジニアではなく、チームのルールを見ているだけです。これは私に何の関係がありますか?

チームがフックでルールを強制しているなら(例:ファイル削除の禁止、mainへの直接プッシュの禁止)、エンジニアにシンプルな質問ができる。「ガードのスクリプトが壊れたりタイムアウトしたらどうなるか」。既定の答えは通過で、画面には見落としやすいエラーが1行出るだけだ。重要なルールにonFailure: "block"が設定されているか、そしてこのゲートがまだ機能していることを誰かが定期的に検証しているかを確認する。

全文 +

多くの人がフックを「必ず止める」安全装置だと考えているが、公式のhooksドキュメントははっきり書いている。終了コードだけでアクションを止められるのは2だけだ。それ以外の非ゼロ終了はブロックせず、トランスクリプトにhook errorの行が出るだけ。つまり、ガード用スクリプトが壊れたとき、既定の結果は通過になる。2026年10月8日のv2.1.295は、まさにこの穴を塞ぐonFailure: "block"を追加した。

既定はfail-open:どんなときに通ってしまうか

公式のhooksドキュメントによると、次のいずれもPreToolUseをブロックしない。

  • スクリプトが存在しない、または実行できない:127のような終了コードは非ブロックのエラー扱い。ドキュメント自身が、settings.jsonでパスを打ち間違えるとゲートが静かに無効になると警告している。
  • タイムアウト:command、http、mcp_toolのフックがタイムアウトすると、ツール呼び出しは通常の権限フローに進む。これらの既定タイムアウトは600秒、promptフックは30秒、agentフックは60秒。
  • 終了コード1やその他の非ゼロ値:Unixで一般的な失敗コードも、ここでは警告にすぎない。ポリシーを強制するならexit 2を使うよう、ドキュメントは求めている。
  • HTTPフックの問題:2xx以外のステータス、接続失敗、2xxでもJSONでない本文は、すべて非ブロックのエラー。HTTPフックはステータスコードだけではブロックできず、判断フィールドを含む2xxのJSONを返す必要がある。

v2.1.295のonFailure: "block"

リリースノートの説明では、commandとHTTPのフックについて、フックが起動できない、タイムアウトする、予期しない終了コードで終わる場合に、通過させずアクションをブロックするよう設定できる。Developers Digestが10月9日に公開した検証は、v2.1.295のclaude -pで6つの設定を試し、PreToolUseフックだけを変えた。何も設定しない場合は、スクリプト不在とタイムアウトのどちらでもコマンドが実行され、"onFailure": "block"にすると両方ブロックされ、正常に動くガードは安全なコマンドを通し続けた。

同記事は適用範囲も述べている。意味があるのはPreToolUse、UserPromptSubmit、Stopのようにブロック可能なイベントだけで、prompt、agent、MCPツールのフックは対象外だ。以下の設定例は同記事のものだ(私が読めた公式hooksドキュメントのページにはこのキーが出てこなかったので、使う前に公式ドキュメントかclaude Plugin validateで確認してほしい)。

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/guard.sh",
            "timeout": 5,
            "onFailure": "block"
          }
        ]
      }
    ]
  }
}

ガード用スクリプト自身もfail-closedにする

onFailureだけでは足りない。スクリプトが最後まで走り、内部のコマンド失敗にもかかわらず0で終了すれば、Claude Codeから見ると成功した許可だ。Developers Digestの著者は、エラー処理のないガードがjqのないマシンで0終了し、rm -rfを通してしまう例を見つけた。より堅実なのは、予期しないエラーをすべて終了コード2にする書き方だ。この原則に沿った例を示す(照合ルールは流れを示すためのごく粗いもの)。

#!/usr/bin/env bash
set -euo pipefail
trap 'echo "guard crashed" >&2; exit 2' ERR
cmd=$(jq -r '.tool_input.command')
if printf '%s' "$cmd" | grep -Eq 'rm +-rf +/'; then
  echo "blocked: destructive rm" >&2
  exit 2
fi

ここでtrap ... ERRは、jqがないといった失敗をそのままexit 2に変える。一方、if条件内のgrepが一致しなくて1を返してもtrapは発動しない。

すべてをblockにしない

fail-closedにはコストがある。ガードが頼るHTTPエンドポイントが落ちれば、すべてのBash呼び出しが止まる。フォーマッターや通知のような利便性のフックが壊れたくらいで、セッション全体を止める必要はない。以下は私の推奨で、公式の方針ではなく推論だ。

  • onFailure: "block"は、取り消せない、または悪用されうる操作(削除、プッシュ、認証情報の持ち出し)にだけ設定する。
  • 短いタイムアウトを併用する。公式の既定は600秒なので、固まったガードは最大10分アクションを待たせうる。
  • 正規表現のガードは一層にすぎない。サンドボックスやdenyルールと組み合わせる。

同じ時期の関連する修正

v2.1.294(10月8日)は、指示文として書かれたpromptフックとagentフック(例:「Block commands that…」)が、止めるべきものを通してしまう問題を修正し、StopとSubagentStopのpromptフックの判定も改善して、Claudeが早く止まりにくくなった。それ以前のv2.1.288のノートの要約にも、照合の失敗でPreToolUseフックがスキップされるケースを、今はその呼び出しをブロックするようにした旨がある(詳細は原文を参照)。1か月のうちに「ゲートが守れていなかった」という修正が続いているので、自分のフックを改めて検証する価値がある。

出典:Hooks reference - Claude Code Docs、Do Your Agent Hooks Fail Open? Claude Code vs Codex vs Cursor vs Gemini CLI - Developers Digest、Claude Code changelog - Claude Code Docs、Claude Code 2.1.295 - hooks can fail closed - ai-tldr.dev
図解
hook 失敗時的預設放行與 onFailure: block 的差別腳本不存在、逾時、非預期退出碼三種失敗,預設都會放行動作;在 command 或 HTTP hook 設定 onFailure: block 後改為阻擋Hook Failure Paths: Default Open vs onFailure: blockScript missingexit 127, bad pathTimeoutdefault 600s (command/http)Unexpected exitexit 1 or other non-zeroIs onFailure set to"block" on this hook?command / HTTP hooks onlyNo (default): fail-openAction proceedsgate silently offYes: fail-closedAction is blockedv2.1.295 and laterAlways: exit 2 blocks on blockable events, exit 0 allowsprompt / agent / MCP tool hooks are not covered by onFailureGuard script itself: set -euo pipefail + ERR trap that exits 2Claude Skill Me · claudeskill-me.com
スクリーンショット歓迎。転載時は出典を明記してください。
質問する
10文字以上入力してください
関連記事
Hookに「blocking error」と表示されたのに、ファイルは変更されている?PostToolUseとPreToolUseの「ブロック」は同じ意味ではない
practice · 09/28
Claude Code 2.1.299へ上げる前に確認:MCP allowルールの厳格化、名前に妙な文字を含むスキルの除外、UserPromptSubmitフックの実行順の変更
practice · 10/19
CLAUDE.mdに書いたのにClaudeが従わない?Hooksで「お願い」を「保証」に変える
practice · 08/25
forkサブエージェントは空白から始めず会話全体を引き継ぐ——v2.1.302からVS Code、デスクトップ、ヘッドレスでも既定で有効に
advanced · 10/19
関連ニュース
関連トピック