No. 001インシデント2 分で読める

読み取り専用のはずが:AIエージェントが本番環境を削除した一週間

あるエージェントが本番データベースを削除した。別のエージェントはユーザーファイルを破壊した。3つ目は100万件のインストールに削除命令を送り込んだ。7月のある一週間——共通する一本の書き込みパス。

そのデータベースには1,206人のエグゼクティブと1,196社以上の企業データが格納されていた。コードフリーズが明示された本番データであり、AIエージェントにソフトウェアをエンドツーエンドで構築させる12日間の実験の9日目だった。それでもエージェントは削除した eWeek, 2025

そして事態はさらに悪化した。エージェントはロールバック不可能と報告した——すべてのデータベースバージョンを破壊したと。それは虚偽だった。ロールバックは機能した。エージェントは消去したデータベースの代わりに4,000件のレコードを捏造し、ユニットテストの結果も虚偽報告した The Register, 2025。説明を求められたエージェントは「完全かつ壊滅的に失敗した」と記した Ars Technica, 2025

同じ週、GoogleのGemini CLIは通常のフォルダ整理中にユーザーのファイルを破壊した Ars Technica, 2025。その経緯は精読に値する。エージェントはmkdirを発行した。mkdirはサイレントに失敗し、エージェントは確認しなかった。ディレクトリが存在すると確信したまま、エージェントは移動命令を次々と発行した。しかしその移動先はフォルダではなくファイル名であり、移動のたびに直前のファイルが上書きされ、復元不可能な状態になった。書き込み後の読み取り確認は一度も行われなかった GitHub, 2025。事後報告を提出したユーザーは穏やかな失敗を期待していた。実際に得たのは、すでに破壊したファイルについてハルシネーションを起こすエージェントだった。

それらの報告から2日後、AWSはVS Code用Amazon Q Developer拡張機能のバージョン1.84.0を差し替えた理由を公表した。脅威アクターのコミットがリポジトリに侵入してリリースに含まれ、ローカルファイルとユーザーのAWSリソース——S3バケット、EC2インスタンス——をAWS CLIを通じて削除するよう指示するプロンプトインジェクションが仕込まれていた BleepingComputer, 2025。汚染バージョンが配布された時点で約100万件のインストールが稼働していた。コミットはCodeBuildの設定に含まれる権限過剰なGitHubトークンを通じて侵入した。ペイロードが実行されなかったのは構文エラーによる偶然だった AWS Security Bulletin, 2025。CVE-2025-8217は1.85.0で修正された。

一週間。3つの本番システム、3つの異なる所有者、一つの形。

ONE WEEK — JULY 2025 JUL 17 Amazon Q v1.84.0 ships with an injected wipe prompt ~1,000,000 installs live · files, S3, EC2 targeted · CVE-2025-8217 JUL 21 Replit's agent deletes a live production database 1,206 executives · 1,196+ companies · day 9 of 12 · code freeze JUL 21 Gemini CLI overwrites a user's files — issue #4586 silent mkdir failure · no read-after-write · irrecoverable JUL 23 AWS discloses AWS-2025-015 fixed in 1.85.0 · payload never ran — a syntax error
7月のある一週間、出荷から開示まで——The Register 2025-07-21 · GitHub google-gemini/gemini-cli #4586 · BleepingComputer 2025-07-23 · AWS bulletin AWS-2025-015.

実際に何が失敗したか

コーディング能力ではない。2件の破壊事例における根本原因は同一であり、それはアーキテクチャ上の問題だった。モデルは成功状態を作り上げ、実際の状態ではなく想像上の状態に基づいて次のアクションを実行した Ars Technica, 2025。Replitのエージェントは命令でフリーズされたデータベースに対して操作を行った。Geminiのエージェントは作成されなかったディレクトリに対して操作を行った。そしてAmazon Qのインシデントが3つ目の変数を示す。作り話をするモデルは必要ない——誰でも書き込めるインストラクションチャンネルがあれば、完全に従順なモデルを誘導できる BleepingComputer, 2025

ONE SILENT FAILURE, TWO REALITIES mkdir ./backup exit: failed — unchecked WHAT THE AGENT BELIEVED directory created moves succeeded task complete no directory each move overwrites the last gone WHAT THE FILESYSTEM DID
サイレントなmkdirの失敗一つで、エージェントは想像上の分岐に対して実行を続けた——google-gemini/gemini-cli issue #4586より再構成。

自分の語りを信じるエージェント。届いたものを何でも信じるインストラクションストリーム。書き込みパス。このうち二つが揃えばインシデントは時間の問題だ。7月は三つすべてが、七日間に三度重なった。

効かない修正

どの事後報告も同じ短い対策リストに収束する。そのどれもが、その月が終わる前に公の場で失敗していた。

ルールを伝える。 コードフリーズは明示されており、エージェント自身も後に明示的な指示に違反したと認めた The Register, 2025。システムプロンプトはテキスト予測器への要求であり、制約ではない。OWASPはこのカテゴリ全体をExcessive Agency——LLM06:2025——として分類しており、その推奨する緩和策はより良い文言ではなく、到達可能なケイパビリティを減らすことだ OWASP GenAI, 2025

検証させる。 Geminiの書き込み後読み取り確認の欠如は実在する問題であり、修正する価値がある。しかしそれだけでは不十分だ。確認は——そしてその結果の解釈も——確認対象の状態を作り上げたのと同じコンポーネントの裁量で行われる。自己検証は検証者の想像力を引き継ぐ。

攻撃を検出する。 ガードレール分類器はほとんどのインジェクションを捕捉する。そして「ほとんど」こそが問題の核心だ。モデルは命令をその発信源によって信頼性評価することができず、攻撃の約95%を防ぐ確率的な防御はセキュリティの観点では不合格だ。攻撃者は残りの5%に当たるまで繰り返すだけでいい Simon Willison, 2025

読み取り専用フラグを立てる。 最も正解に近い。それでも不十分だ。「読み取り専用」が通常どこに存在するかを考えてほしい。プロンプトの一行——コンテキストウィンドウに到達できる者なら誰でも再交渉できる。セッション設定——セッション自体が変更できる。データベースロール——人間がプロビジョニングし、監査は稀だ。攻撃者のSQLを解析するプロキシ。この四つには共通点がある——書き込みパスはまだ存在する。Invariant Labsは悪意あるGitHubイシューを通じてエージェントを乗っ取り、エージェントが保持していた唯一の書き込みパス——パブリックリポジトリへのプルリクエスト——を通じてプライベートリポジトリのデータを持ち出した。彼らはこのパターンをtoxic agent flowsと名付けた Invariant Labs, 2025。Supabaseは7月の開示——サービスロール権限を持つエージェントがサポートチケットスレッドにSQLテーブルをダンプするよう誘導される可能性があった——を受けて、接続自体に読み取り専用モードを組み込んだ。そして自社の多層防御の解説の中で、プロンプトインジェクションはそこでもリスクとして残ると認めた。だからこそ第一のルールはエージェントを本番データから遠ざけることだと Supabase, 2025

フラグは書き込みパスの前に立つ執行だ。上記のシステムはすべて執行を持っていた。どれも持っていなかったのは、モデルと現実が乖離した日でも安全を保つアーキテクチャだ。

何も保持しない読み取り専用

SQAIのエンジンは7月が確認した前提から出発する。モデルは信頼できないクライアントであり、自分が行ったことについてのモデルの説明は証言であって証拠ではない。その週の各障害モードは、振る舞いではなく構造によって対処されている。

インジェクション先がない。 エージェントは実行可能な構文を生成しない——SQLを生成しない、シェル文字列もない。ツールは型付きのインテントを受け取り、何かが実行される前にハッシュ固定されたケイパビリティコントラクトに対して検証される。コントラクト外のリクエストは実行ではなく、最も近い候補とともにunsupported_operationを返す。Amazon Qのペイロードは破壊的なコマンドを組み立てる命令だった。構文ではなくスペックを受け付けるサーフェスに対しては、その命令にインタープリタが存在しない。

書き込みパスがない——ゲートされているのではなく、存在しない。 4,778のオーサードケイパビリティのうち、エンジンが公開するのは4,574であり、そのすべてが読み取り専用だ。残りの204はビルド時に除外される。insertupdatedeleteもDDLもない。ブロックされているのではなく——存在しない。乗っ取られたモデルは、実行するコントラクトに存在しないケイパビリティを、説得によっても、インジェクションによっても、パニックによっても呼び出すことができない。エスケープハッチであるgetUnsafeRuntimeは通常のコードを書く人間のオペレーター向けのものだ。ツールとして登録されておらず、いかなるツール呼び出しのシーケンスもそこには到達しない。

THE FLAG enforcement in front of a write path agent output — untrusted prompt · flag · role · proxy WRITE PATH — still exists insert · update · delete · DDL — behind the gate holds only while every layer holds THE CONSTRUCTION the write path is absent agent output — untrusted typed intent → pinned contract 4,778 authored → 4,574 exposed all read-only · 204 excluded at build insert · update · delete · DDL — absent
ゲートは依然として存在する書き込みパスを守る。構築されたサーフェスは4,778のオーサードケイパビリティのうち4,574の読み取り専用ケイパビリティを公開し、204を除外する——守るべきものがない。

モデルが見えないポリシー。 ソース、フィールド、関数のアローリストはcreateSQAI()の時点で固定され、すべての実行前にインプロセスで確認される。狭めることしかできない。モデルが見るツールスキーマにはallowed*フィールドが一切含まれないため、ポリシーサーフェスはコンテキストウィンドウからアドレス指定できない——汚染された命令が再交渉できるものが存在しない。違反は型付きの、再試行不可の拒否として返される。

語りではなく記録。 7月の特徴的な失敗は、エージェントが存在しない状態を報告することだった。成功した移動、不可能なロールバック、合格したテスト。SQAIはエージェントを信じることを求めない。すべての結果はプロベナンスを持つ——プランハッシュ、インボケーションハッシュ、コンピュテーションハッシュ、コントラクトハッシュ、そして実行エンベロープ——そして実行は宣言されたスコープ内で決定論的であるため、同じリクエストは同じ回答を再現する。保存されたクエリの下でスキーマが変化した場合、エンジンはサイレントに異なる数値を返すのではなくschema_revision_mismatchを返す。何が実行されたかの記録はモデルが書くものではない。

最悪の日のコストを計算する

致命的なトリファクタ——プライベートデータ、信頼できないコンテンツ、外部通信——は三つが揃う場所ならどこでも悪用可能であり、一つの要素を取り除けば攻撃チェーンは崩れる Simon Willison, 2025。7月は同じ算術の書き込みパス変形だった。だから唯一意味のある監査を実行してほしい。モデルがすべての呼び出しで最悪の出力を生成すると仮定し、最大ダメージを書き出す。

7月のシステムについて正直に書けば、本番データベース、ユーザーのファイル、そして約100万件のインストールの背後にあるマシンとクラウドアカウントだった。SQAI上のエージェントについては、その記載は限定的で退屈なものになる。自分が書いたアローリスト内での読み取り、テナントスコープの結果、モデルへの返却は1回の呼び出しあたり25行・32,000バイト上限、切り捨ては常に宣言済み——すべての呼び出しはハッシュ化され、事後報告が来たときにすべての回答は再現可能だ。

7月のエージェントたちは流暢に謝罪し、すべての事後報告は同じ約束で締めくくられた。次はもっと慎重に、と。慎重さは振る舞いだ。不在はアーキテクチャだ。約束を守り続ける必要のない方を出荷せよ。