
CrowdStrikeのクラッシュはフィールド数に起因した:カーネルが20個を想定していた箇所に21個。独立した検証レイヤーは存在しなかった。
2024年7月19日、たった1つのベンダー更新プログラムが90分足らずで何百万台ものWindowsマシンをクラッシュさせました。そしてその原因は単なる1つの数値でした。CrowdStrikeの「Rapid Response Content」チャネルファイルが、デプロイ済みのカーネルインタープリターが20個を想定していた箇所で21個のフィールドを宣言していたのです。その余分なフィールドが範囲外読み取り(out-of-bounds read)を引き起こし、即座のブルースクリーンを発生させました。さらにクラッシュがブートのごく初期段階で起きたため、停止したエージェントはロールバックコマンドを受け取るために再起動することすらできませんでした。復旧作業とは、各マシンの元へ物理的に歩いて行き、セーフモード(Safe Mode)で手動修復することを意味していました。
私はその年の8月に公開されたCrowdStrike自身の根本原因分析(RCA)を、自分の中で違和感が明確になるまで何度も読み返しました。これはハッキングではありませんでした。不適切なAIモデルによるものでもありませんでした。本番環境に到達する前にいかなる独立したレイヤーによっても検証されなかったペイロードの中に潜んでいた、21対20という判定可能な算術的事実だったのです。ベンダーのバリデーターはそれを承認しました。停止に追い込まれた企業はそのバリデーターを所有していませんでした。企業が引き受けたのはその結果だけだったのです。
私は直近の期間を費やして、その隙間を埋めるデモを構築しました。ソフトウェアベンダーと本番環境フリートの間に位置し、ベンダーが何をリリースしてよいかをコードによって判断する、Kestrelと名付けたコンソールです。その動作は次のURLで確認できます:veriprajna.com/demos/software-update-integrity。構築中に私を驚かせたのは、真の解決策がどこに存在していたかという点でした。当初はより賢いモデルが必要になると確信して取り組んだものの、最初にクラッシュを捕捉したのはわずか数行の素のPythonコードだったのです。
クラッシュを再現し、コードに判断を委ねた
私は7月19日の障害シグネチャをテスト用フィクスチャとして再現し、自作のシステムに対象として入力しました。自らのリプレイに拍子抜けするのではないかという半信半疑の思いもありました。パッケージはC-00000291、私がSentinelEdgeと名付けた架空のベンダーによるRapid Response Contentチャネルファイルであり、Acme Financialと名付けた8,500台の合成エンドポイントフリートに向けて配信されたものです。これらは実在する企業ではありません。しかし障害シグネチャは本物です。宣言されたスキーマが20から21に増大し、カナリア計画なしに単一の波でフリートの100%に一斉プッシュされたのです。
ゲートは4つのチェックを同時に起動します。そして各チェックは純粋な算術演算または単純なルックアップであり、主観的な判断ではありません。スキーマ比較はインタープリターが20を想定する箇所に21個のフィールドを検出し、範囲外読み取りをフラグ付けします。実際のWindows VMファームではなくプロファイルごとの決定論的結果モデルであるシミュレートサンドボックスは、再起動サイクル全体でフリートの6プロファイル中5プロファイルをブートループに陥らせます。しかもスキーマチェックとは独立したドライバ互換性シグナルからこれを導出するため、2つの所見は単なる同語反復ではなく相互に裏付け合います。デッドエージェント検出器はロールバックループをtrueと判定します。なぜなら、クラッシュしたエージェント自身がロールバックを受け取る対象であり、ブート完了前にダウンしているからです。影響範囲(ブラストラディウス)は5%のカナリアポリシーに対して100%に達します。判定:BLOCK。画面には「本番エンドポイントが1台も再起動する前にブロックされました」と表示されます。

その1つの更新プログラムによる推定ダウンタイム回避額は5,000,000ドルと表示されますが、私はその数値が何を意味するのかを正確に述べておきたいと思います。それはデモ独自の内蔵モデルであり、影響を受ける割合に時間あたり500万ドルの入力値を掛け、さらに1時間の最低復旧時間を乗じたもので、画面上に計算式が明記されています。顧客が実際に節約した金銭ではありません。7月19日の実際の復旧には1時間ではなく数日を要したため、最低値は意図的に極めて保守的に設定されています。
緑のケースは赤のケースよりも私を不安にさせた
私は赤のケースよりも緑のケースに対してより神経質になっていました。なぜなら、危険な更新を阻止すると同時に安全な更新までも締め出してしまうガバナンスレイヤーは、自らスケジュールしたサービス停止に他ならないからです。同じ架空のベンダーが、無害な検知シグネチャ更新であるRRC-7741(宣言スキーマ20対20、段階的な1.2%のカナリア計画付き)を配信します。エージェントクルーが実行され、スキーマは一致し、6プロファイル中5プロファイルが再起動サイクルをクリアし、デッドエージェントループはfalse、影響範囲はポリシー内に収まります。判定:APPROVE ROLLOUT。102台のエンドポイントのカナリアリングにリリースされました。グリーンで、迅速で、平穏な結果です。

セット内の6つの無害な更新全体を通して、ゲートが生成した誤検知ブロックはゼロでした。私が分母を明記して述べるのは、6件はあくまで6件であり、それを皆さんのフリートに対する保証へと誇大に丸め込むことを許さないからです。ALLOWケースの価値はパーセンテージよりも限定的であり、かつより重要です。ゲートの信頼性は、通常のトラフィックでは不可視であり、フリートを倒壊させかねない唯一の局面において決して揺るがないことによってのみ証明されます。
なぜ判定の権限をモデルから外したのか
私は当初、最も困難な部分は推論であり、より先鋭化されたモデルや巧妙な批評エージェントこそが不正な更新を捕捉するものだと想定して構築を始めました。しかしその考えは誤りであり、それを認めるまでにしばらく時間を要しました。Kestrel内部にはLLMクルーが存在します。ノーマライザー、サンドボックスインタープリター、そして更新の安全性を主張する側とクラッシュを主張する側の2つの対立する批評エージェントです。この対抗ペアは何かが決定される前に双方の方向から判定をレッドチーム検証するため、その存在意義を果たしています。しかし、それらのエージェントの誰一人として最終判定を下すことはありません。
判定を下すのは、2つの素のPythonファイルであるverifier.pyとgate.pyであり、これらはエージェントフレームワークの完全に外部に配置されています。クルーはデフォルトモデルとしてclaude-opus-4-8を採用したPydantic AI上で動作し、システム全体はAPIキーなしの決定論的助言フォールバックによりオフラインでも動作します。これらすべてのモードにおいてゲートは同一であり、同じ決定を返します。なぜなら決定は算術演算であり、推論ではないからです。エージェントは助言し、コードが決定します。「許可」に傾く助言エージェントであっても、重大な決定論的所見を帳消しにすることはできません。そしてそれは好みの問題ではないのです。
ベンダーを検証するために構築されたレイヤーが、安全性についてベンダーの言い分を鵜呑みにすることはできません。自らのモデルの言い分を鵜呑みにすることも許されないのです。
その一文こそが、このアーキテクチャが現在の姿をしている理由です。ベンダーが配信するものを統制することのみを職務とする製品への信頼は、「はい」と言いくるめられる可能性のあるコンポーネントを経由しては決してならないのです。
私が監査人に提出するもの
証拠記録を構築している間、私はセカンドモニターにEUサイバーレジリエンス法(CRA)を開き続けていました。なぜならその記録こそが、私が実際に防御しなければならないアーティファクトだからです。すべての決定は、SHA-256コンテンツハッシュ、判定、決定論的証明、プロファイル別サンドボックス結果、助言エージェントのモデルID付き判定、トリガーされたポリシー規則、および各ステップが個別のレイテンシを保持するステップ別評価トレースを含む、不変のHTMLファイルと署名付きJSONファイルを出力します。

トレースは、個別のステップをクリックしてみるまで私が過小評価していた要素でした。あるイベントには「署名済みベンダーマニフェストの正規化、184ミリ秒で完了」と記されており、監査レビューのために決定出力とともに保持されます。すべてのステップが再導出可能です。規制当局は私のダッシュボードを盲信する必要はありません。算術演算を再実行すれば、まったく同一の回答が得られるのです。

私はこの署名が何であり何でないかについて慎重を期しています。これはローカルのSHA-256であり、エンタープライズPKIではありません。ベンダー更新フィードとその背後にあるITSMチケットはフィクスチャスタブであり、ライブコネクタではありません。この記録は提出要件に適合するよう設計されています。CRAの短期間インシデント報告、SECによる重要サイバーセキュリティインシデントの4営業日以内の開示義務、2025年にフルトン郡で提起されたDelta対CrowdStrike訴訟で浮き彫りになったベンダー責任問題などです。「適合するよう設計されている」のであって、誰かを認証するものでも法的助言でもありません。そして準拠状態になれると謳って監査ログを売り込もうとする者は、単に商品を売りつけようとしているに過ぎません。
私が誇りに思っている決定がもう1つあります。それは「拒絶」です。フィクスチャXX-0000はゲートが解析できない暗号化された独自コンテンツのバイナリ(blob)であり、ゲートは推測を行いません。ABSTAIN(棄権)を返し人間へエスカレーションします。なぜなら読めないものを素通りさせるゲートは、ゲートがまったく存在しないことよりも有害だからです。サンドボックスがモデル化できないレガシーホストはフラグが立てられて除外され、安全であると見なされることは決してありません。語彙はALLOW、HOLD、BLOCK、ABSTAINの4語であり、最後の1語こそ私が最も頑なに死守する言葉です。
12件中12件という結果が意味することを許される範囲
ここで私はペースを落とさなければなりません。なぜなら、創業者というものはまさにこの段階で都合よく数値を丸め始めるものであり、私は会社に真の知恵を意味する「Veriprajna」と名付けた以上、誇大な丸め込みは論外だからです。12件の固定・ラベル付けされた更新セットにおいて、ゲートは12件すべてで正しい決定を下します。そのうち6件は無害であり、1件もブロックしません。1件は誠実なABSTAINです。スコアボードには、12/12件の検証済み決定、0/6件の誤検知ブロック、そしてセット全体で推定13.3Mドルのダウンタイム回避額が表示され、そのうち500万ドルが単一のCrowdStrike級ブロックによるものです。

ここからは私が省略を拒否する部分です。これらは12個のラベル付けされた項目における結果であり、皆さんのフリートに届く次の更新に対する保証ではありません。6件の無害な項目はあくまで6件です。これは「不正な更新を100%遮断する」という意味ではありませんし、今後もそうなることはありません。もし私がそんな文言を書いているのを見かけたら、私の文章を読むのをやめるべきです。私が保証する数値は異なる性質のものです。判定にモデルの温度パラメーターが含まれないため、実行するたびに同じ入力に対して同じ決定が下されます。明日フィクスチャセットを再実行してもバイト単位で同一の結果が得られます。それこそが、確率論的レイヤーでは不可能な方法で決定論的レイヤーを監査可能にする本質なのです。
私の中に残された問い
この構築を通じて私の心に強く残っているのは、その障害がいかにありふれたものであったかということです。20個が想定されていた箇所に、21個のフィールドが存在したこと。もしベンダーとフリートの間に独立した検証機構が介在していれば、1台のマシンが再起動する前に、いかなる独立検証者でも単純な算術演算によって捕捉できたはずの数値でした。しかし、そこには何も存在しませんでした。そして今日でも、依然としてほとんど存在していません。
あらゆる企業が、自ら制御できないベンダーからのカーネル権限を持つエージェントを8〜12個稼働させており、その各々がファイルを直接リング0(ring 0)へと送り込むことができます。SBOMツールはオープンソースの依存関係を監視します。アイデンティティ管理はアクセスを監視します。しかし、侵入経路においてベンダー独自の更新プログラムを読み取り、安全性を証明する者は誰もいません。KestrelはEDRではなく、カーネルに触れることもありません。それらのエージェントの上位に位置し、配信が許可されるものを統制します。それこそが私が構築を試みたレイヤーであり、その全容は次の場所にあります:veriprajna.com/demos/software-update-integrity。
そして私の文章を読むよりも実際の動作を見たいという方のために、エンドツーエンドで稼働するシステム全体が用意されています。
ですから、私が目にするすべてのフリートに対して今問いかけたいのは次のことです。次回のベンダー更新が届いたとき、そのファイルと本番環境の間には何が立ち塞がり、自らの検証プロセスを証明できるのか?もしその答えがベンダーを無批判に信用する変更諮問委員会(CAB)であるなら、何百万台ものマシンをダウンさせたあの算術的不整合は、今なおチェックされることなく進行しています。それは自らを予告することはありません。再起動のその瞬間まで、過去に届いたあらゆる正常な更新とまったく同じ姿をしているはずです。

