これは、AIコーディングエージェントに関する恐怖の物語シリーズのパート5です。AIコーディングエージェントに関連する実際のセキュリティインシデントと、 Dockerサンドボックスがエージェントの実行をコマンドラインではなく境界でどのように制限するかについて見ていきます。
パート1では、AIコーディングエージェントの失敗の6つのカテゴリと、それらが繰り返し発生する理由について説明しました。エージェントは、あなたのファイルシステム権限と認証情報を使用して、あなたとして実行されます。モデルの決定とシェルの実行の間には、何も介在しません。パート2では、 rm -rf ~/事件について詳しく解説しました。パート3では、同じ問題を本番環境のクラウド環境に移行しました。パート4は、サプライチェーン攻撃を通じて認証情報自体を追跡した。
これはセーフティネットに関する話です。現在、コーディングエージェントを運用しているほとんどのチームは、エージェントが許可なく実行できるコマンドのリストを何らかの形で作成しており、その根底にあるのは、危険なコマンドはすべて拒否できるプロンプトとして表示されるという前提です。1月、 Pillar Securityの研究者たちは、この前提が成り立たないことを示した。
今日のホラーストーリー:承認が思わぬ事態を引き起こした
14 、 2026 1 月、 Pillar Securityの研究者は、Cursor の脆弱性である CVE- 2026 - 22708を公開しました。エージェントを許可リストを有効にした自動実行モードで実行した場合、許可リストに記載されていないにもかかわらず、また承認を求めることなく、少数のシェル組み込みコマンドが実行された。エージェントの前にテキストを表示できるものであれば何でも、例えばREADMEファイルや依存関係、あるいは問題に関するコメントなどであれば、それらを利用して環境変数を密かに変更することが可能です。開発者が承認したコマンド、例えばgit branchようなごく普通のコマンドでも、攻撃者のコードが実行されてしまう。Cursor はこれを高評価し、バージョン2 . 3でパッチを適用しました。
今回の件ではメモリ破損は発生しておらず、権限の昇格も行われていません。開発者には正確なプロンプトが表示され、全く無害なコマンドを承認したにもかかわらず、任意のコード実行が可能になってしまった。なぜなら、そのコマンドの意味が、開発者には一切知らされていなかった何らかの要因によって、わずか1分前に変更されていたからだ。
今号では、次のことを学びます。
- シェル組み込み関数が、設計どおりに機能していた許可リストをすり抜けた経緯
- 許可リストが完全に空だったのに、なぜ攻撃が成功したのか
- Dockerサンドボックスには何が含まれているか、そして含まれていない2つのもの
- キット、組織ポリシー、監査ログが、ラップトップごとの許可リストではカバーできない部分をどのように補うか
キャプション:承認プロンプトを表示せずに環境設定を変更するインジェクション命令によって、開発者が正当に承認したコマンドが攻撃者のペイロードを実行するようになる様子を描いた漫画。
問題を
通常、プログラムは起動時に環境設定を読み込みます。Git はPAGERというファイルをチェックして、どのプログラムが出力を表示するかを判断し、Python はPYTHONWARNINGSというファイルをチェックします。誰もこれらのことを考えない。それこそが重要な点なのだ。それらを変更するコマンドはシェルの組み込みコマンドであり、Pillar の研究では特にexport 、 typeset 、 declare名前が付けられており、詳細は開示時に独自に報告されている。組み込みプログラムはディスク上に存在するプログラムではないため、チェッカーはディスク上のプログラムを検索していたため、組み込みプログラムは検出されることなく通過しました。
つまり、攻撃全体はたった2行で構成されているということだ。
# This one runs silently. You are never asked.
export PAGER="open -a Calculator"
# This one you are asked about, and you say yes, because obviously.
git branch
GitはPAGERを調べてブランチリストを表示する方法を調べ、その中に攻撃者のコマンドがあることを発見し、代わりにそれを実行した。Pillar社は、最も制限の厳しい設定である、完全に空の許可リストでもこの機能が動作したと指摘している。
許可リストは、その前に指定されたコマンドがリストに含まれているかどうかをチェックします。これは中断を減らすのに有効で、朝に 90 回もlsコマンドを承認したい人はいません。しかし、コマンドの名前だけでは、そのコマンドが何をするのかはわかりません。小切手は名前を読み取り、通過させるが、実際に何が起こるかを決定する設定は、小切手には一度も表示されなかった何らかの要因によって、1分前に変更されていた。
Cursorのドキュメントでは、許可リストはベストエフォート型であり、回避される可能性があることを警告している。ピラー氏はさらに踏み込んで、エージェントには隔離された環境内で完全なコマンド実行権限を与えるべきであり、業界は許可リストを完全に廃止すべきだと主張した。
問題の規模
根本的なトリックはどれも新しいものではない。Pillar の解説は、環境変数に関する Elttam の研究2020に言及しており、これらの設定がコード実行に変換できることを示していました。
それは6年間、誰にもほとんど迷惑をかけることなくそこに放置されていた。それを実行するには、既に他人のマシンにアクセスしていること、いくつかの手順を正しい順序で設定していること、各ステップを自分で実行していることが必要だった。そして、それほどのアクセス権を持つ者であれば、もっと迅速に損害を与える方法も持っていた。
すると、コーディングエージェントが現れ、それらの障害を全て一気に取り除いた。彼らは、読み込むように指示されたファイル内の指示に従って行動し、チェックのために停止することなく複数の手順を連続して実行し、あなたと同じように動作します。かつては誰かがキーボードの前に座って作業する必要があった技術が、今では今朝クローンしたリポジトリの中に簡単に手に入るようになった。
これはパート4のs 1角特異点攻撃と同じ形状です。そこで、毒物が仕込まれたパッケージが、既にログインしていたエージェントを借り出した。ここでは、悪意のあるテキストが、既に承認されているコマンドを借用している。どちらも何も壊さない。両者とも、誰も意図していなかった目的で、意図的に与えられた許可を利用している。
技術的な詳細:攻撃の仕組み
キャプション:注入された命令がシェル環境を人知れず変更し、開発者が承認した際に、許可リストに登録されたコマンドが攻撃者のペイロードを実行する仕組みを示す図。
この攻撃は二つの段階から成り立っており、その二つの段階をうまく切り分けることが肝心な点だ。
1 。決して目にすることのない半分
エージェントは、読み取るように指示されたファイルを読み込みますが、そのファイルにはあなたではなくエージェント自身に向けた指示が含まれています。内蔵機器は、静かに環境を整える。画面には何も表示されません。
Pillar はこれのより長いバージョンを実証し、 PYTHONWARNINGS 、 BROWSER 、 PERL 5 OPTなど複数の設定を連結して、そのマシン上の以降のすべてのpython 3コマンドが攻撃者のコードを実行するようにしました。詳細は異なるが、原理は同じだ。プログラムが起動時に読み込む内容を変更すれば、そのプログラムの動作も変わる。
2 。あなたが賛成する半分
次に、 git branchまたはpython 3 script.pyを実行します。または、エージェントがあなたの許可リストに基づいて実行します。これらは、頻繁な割り込みを止めるために人々が許可リストに追加するコマンドです。したがって、リストの調整が適切であればあるほど、トリガーがより確実に作動します。ペイロードはあなたの権限で実行されます。
一部のバリエーションは、承認手続きを一切経ない。~/.zshrcに追加の行を書き込むと、そのため、ターミナルを開くたびにコードが再度実行されます。プロジェクトを完了させ、リポジトリを削除しても、来月も引き続き実行できる可能性があります。
影響
Pillar社の調査によると、一連の流れは最終的に被害者のSSH秘密鍵がマシンから流出するところで終わる。
逆算してみると、すべてはファイル内のテキストから始まり、エージェントが指示されたとおりにテキストを読み取ったことから始まったのだ。メモリに関するバグはありません。権限昇格は行われません。どのログにも、少しでも不審なものは一切ない。
Pillarは8月にこの問題を報告し、修正プログラムは同年1月にリリースされました。2025カーソルがレポートに反応し、実際に変更を加えたため、パーサーが分類できないものはすべて承認が必要となり、これまで示されていた経路は閉じられました。5ヶ月という期間は、ベンダーに対する苦情というよりは、問題が発見された層で修正するのがいかに困難であるかを示す適切な指標と言えるでしょう。
根本的な問題は何も解決していない。なぜなら、そもそも問題はシェルに組み込まれた機能だけではなかったからだ。それは、誰かが周囲の家具を並べ替えている間に、命令を研究するチェックに関するものです。
キャプション:マイクロVM内で実行される同じペイロードと、そこからアクセスできる範囲とアクセスできない範囲を示す図。
Dockerサンドボックスが実行層でこれをどのように封じ込めるか
Docker Sandboxは、AIコーディングエージェントを隔離されたマイクロVM内で実行します。各マイクロVMは独自のカーネル、ファイルシステム、およびデフォルトで拒否されるネットワークを備えているため、エージェントが取得した侵害された依存関係がホスト、その認証情報、または他のワークロードに到達することはありません。そのボックス内では、エージェントはsudoを使ったものも含め、あらゆるものを実行できます。これはまさにPillarが推奨する方法です。抜け出せる許可リストなど存在しない。共有カーネルがなぜこの用途には不適切な形状なのかについては、「信頼できない自律型ワークロード」でより詳細な議論を展開しました。
それでは、同じ攻撃を今度はサンドボックス環境で実行し、それがどこまで到達するかを観察してください。
注射はちゃんと命中する。環境が変更されても、 git branch依然としてトリガーとなり、ペイロードが実行される。サンドボックス環境であっても、それを妨げるものは何もない。するとペイロードはSSHキーを探しますが、見つかりません。ホームディレクトリは境界の向こう側にあるため、 ~/.ssh/id_rsaは存在しません。コピーするボックスの内側。
それでも鍵は使用できる。SandboxesはSSHエージェントソケットをボックス内に転送するため、 git pushなどの通常の作業は引き続き機能します。つまり、内部のコードはそのエージェントに認証を依頼することができます。鍵をどこにも持ち運ぶことはできませんが、サンドボックスが実行されている間は鍵を借りることができます。SSHは接続する前に正確な宛先アドレスとポートを指定するルールが必要となるため、ネットワークポリシーによって制限されます。
~/.zshrcトリックは完全に失敗します。なぜなら、そのファイルはホスト上に存在し、ボックス内に書き込まれた不正なコピーはボックスと共に消えてしまうからです。
データを取り出すのは、人々が想像するよりも難しい。HTTPとHTTPSは、ホスト上のプロキシを経由してのみ送信され、プロキシはすべてのリクエストをルールと照合します。TCP経由のその他の通信には、アドレスとポートを指定するルールが必要であり、UDPとICMPは完全にブロックされます。
2つの注意点があり、どちらもDockerのセキュリティドキュメントに明確に記載されています。1つ目はワークスペースで、これはデフォルトでホスト上で稼働しているため、GitフックとMakefileターゲットは引き続きアクセス可能であり、不正なフックはgit diffには表示されません。--cloneオプションを指定して実行すると、エージェントに独自のコピーが渡されます。
2つ目は、共有エージェントスキルストアです。サポートされているエージェントは、作成時にオプトアウトしない限り、ホスト側のストアの読み書き権限をマウントします。これにより、エージェントはスキルを改良して保持することができます。そのストアを共有するすべてのサンドボックスは、1つの信頼境界内に存在するため、あるサンドボックス内で変更されたスキルは、それをロードする次のサンドボックスへの入力となる。ただし、ストアはサンドボックス状態であり、変更されたスキルはそれ自体ではホスト上で実行されないため、リスクはサンドボックスからサンドボックスへではなく、サンドボックスからホストへと発生します。
孤立には、それなりの欠点がある。7月、Pillarは4つのコーディングエージェントにわたる一連のサンドボックス脱出方法を公開したが、そのメカニズムはサンドボックス自体が壊れていたのではなく、サンドボックス内に書き込まれたファイルを外部のツールが後から信頼するという仕組みだった。上記の2つの注意点はどちらもその形状に関するものです。
これらのどれも注射を止めることはできない。これは、注射が到達できる範囲を変えるものであり、この問題の中で唯一確実な答えが得られる部分である。
キットを使って境界線を明文化する
キャプション:キットがエージェントのツール、ファイル、ネットワークルールを宣言する様子を示す図。実際の認証情報はホスト上に保持され、送信時にフォワードプロキシによって挿入される。
この許可リストが機能しなかった理由の一つは、それが各ノートパソコン上で編集されるリストであり、インジェクション攻撃によって回避される可能性があるためです。キットは、各ノートパソコンで編集作業を行うというニーズに対するDockerの回答です。
キットとは、サンドボックスエージェントに認証情報、ネットワークポリシー、環境変数、起動コマンド、ファイルを追加する宣言型のYAMLアーティファクトです。各開発者が個別の許可リストを管理するのではなく、境界を一度記述し、デフォルトでネットワークを拒否し、タスクが本当に必要とする宛先のみを許可し、同じツールキットを全員に配布します。リポジトリ内の他のファイルと同様に、レビュー、バージョン管理、差分比較が行われます。キット仕様のリファレンスには各フィールドが記載されており、 docker/sbx-kits-contribには動作するサンプルが含まれています。
これはまさに上記のSSHに関する質問に直結する。転送された SSH エージェントは、ネットワーク ポリシーによってのみ制限される有効な認証情報です。そのため、そのポリシーをsbx policy deny実行することを覚えている人に任せるのは、この投稿全体で指摘してきたラップトップごとの弱点と同じです。キットにはネットワークルールを組み込むことができるため、信頼できない作業は、宛先が事前に宣言されていない限り、SSH経由で外部に送信されることはありません。
実際の様子
脆弱性はエディタにあるため、必要なのはエディタのターミナルをボックス内に配置する設定です。CursorはVS Codeをベースに構築されており、リモートSSH経由で同じように接続します。エディタはユーザーのマシン上に残りますが、ファイル、ターミナル、拡張機能はサンドボックス内で実行されます。Docker Sandbox 0.37.0以降、SSHアクセス設定、およびCursorのリモートSSHサポートのインストールが必要です。カーソル統合ガイドには、詳しい手順が記載されています。
# One-time setup: configure your SSH client for sandboxes.
sbx setup ssh
# Check the sandbox is reachable, then open the Command Palette,
# run Remote-SSH: Connect to Host, and enter <name>.sbx
ssh demo.sbx
# See what this sandbox is currently allowed to reach.
sbx policy ls
# Shut egress down and open only what the task needs.
sbx policy deny network "**"
sbx policy allow network "github.com,registry.npmjs.org"
最後の2つのコマンドには落とし穴がある。組織でガバナンスが有効になっている場合、組織ポリシーがローカルポリシーに取って代わり、 sbx policy allowおよびsbx policy denyマシンに影響を与えません。sbx policy lsの出力で確認できます。その場合、出力の先頭にGovernance: Managed by <org>という行が表示されます。管理者が設定範囲をどのように指定するかによって、一部のルールタイプはローカル制御に委譲される場合がありますが、ローカルでの許可は組織レベルの拒否よりも優先されることはありません。
同じエディター、同じエージェント、同じ許可リスト、同じペイロード。変更されたのは、端末がどのマシンに接続されているかという点だけだ。
| 何が起こるのですか | ノートパソコンで | 砂場の中 |
|---|---|---|
| ペイロードが実行される | はい | はい |
| 走る場所 | あなたのマシンは、 | 独自のカーネルを持つマイクロVM |
| SSHキーファイル | 読み取りおよびコピーが可能 | そこにはない |
| SSH認証 | 利用可能、鍵付き | 利用可能、鍵は外に置いておく |
| ~/.zshrc のトリック | 無期限に継続する | 砂場と共に消えた |
| データ送信 | デフォルトで開く | ポリシーで許可されている場合のみ |
| 誰がルールを決めるのか | 各開発者 | 組織 |
| その後の証拠 | 何一つ | 記録されたポリシー決定 |
チーム全体でこれを徹底する
キットを使うことで、境界条件を一人の開発者の頭の中からチームが共有するファイルへと変換できるが、それでも重要なマシン上ではファイルが無視されたり編集されたりする可能性がある。Docker AIガバナンスは、設定をさらに一段階上のレベルに引き上げます。ネットワークとファイルシステムのルールは管理者が一度定義すれば、開発者は既に使用しているログイン情報を通じてアクセスできるため、マシンごとに設定する必要はなく、セキュリティによって閉じられたルールを誰かがこっそり再開することもありません。共有キットは、あくまでも提案として境界線を示すものです。ガバナンスは、境界であり天井でもある。
この物語において最も重要なのは、それが記録として残す内容である。CVE-2026-22708が機能した理由は、前半部分が目に見えず、プロンプトも表示されず、探そうと思うような場所に何も書かれていなかったからです。ガバナンスの下では、すべてのポリシー決定によって、ユーザー、タイムスタンプ、および発動したルールを含むイベントが生成され、これらのイベントはセキュリティチームが既に使用しているSIEMにストリーミングされます。
つまり、サンドボックス内で成功した攻撃が、本来到達すべきでない場所へ到達した場合、その痕跡が残るということだ。それは、何も問題が見つからず、誰にも報告しないような検査よりははるかに良い。
ベストプラクティス
1 。export 他のコマンドと同様に 扱ってください 。環境設定を変更するものはすべて、たとえ次のコマンドが許可されリストに登録されている場合でも、次のコマンドの動作を変更する可能性があります。
2 。許可リストを境界と混同しないでください。中断を減らす。ベンダーのドキュメントには、これは最善の努力であり、セキュリティ保証ではないと明記されている。
3 。何かがおかしいと気づいてからではなく、最初のコマンドを実行する前に隔離してください。信頼できないとは、あなたが書いたものではなく、あなたが読んだこともないものすべてを意味し、これは依存関係ツリーの大部分を網羅しています。
4 。検証していないコードには --clone を使用し 、共有スキル ストアへの参加はオプトアウトしてください。そうしないと、Git フックとビルド スクリプトがホスト上で稼働し続け、不正なフックはgit diffに表示されず、あるサンドボックス内で変更されたスキルは、それをロードする次のサンドボックスを待機することになります。
5 。転送されたSSHエージェントは有効な認証情報であることに注意してください。鍵ファイルがマシン上に残っていることと、鍵が使用不能になっていることは同じではありません。そのため、信頼できない作業についてはデータ送信を制限してください。
6 。ご自身のポリシーをお読みください。sbx policy lsを実行します。デフォルトで拒否し、許可リストを長く設定する方式は、見た目以上にデフォルトで許可する方式に近い。
行動を起こす
- Dockerサンドボックスをインストールします。
sbxをインストールし、マイクロVM内で最初のエージェントを実行するには、 Docker Sandboxesのドキュメントを 参照してください。 - エディターを接続してください。リモートSSH統合機能により、端末は境界内に配置され、エディタは元の場所に留まるため、ワークフローは実質的に変わりません。
- キットを使って境界線を明文化する。 チームに必要なネットワークおよび認証ルールを一度定義すれば、個人用の許可リストではなく、同じ成果物を全員に配布できます。
- セキュリティモデルを読んでください。 ドキュメントには、ワークスペースや共有スキル ストアの動作、
--cloneおよびオプトアウト フラグの変更など、何が分離され、何が分離されていないかが明確に記載されています。 - 監査ログを有効にする。 Docker AI Governanceはポリシー決定をSIEMにストリーミング配信することで、サイレントバイパスを実際に調査可能なものに変えます。
結論
CVE-2026-22708の厄介な点は、この話の中で誰も何も悪いことをしていないということだ。
Cursorは、皆が求めていた許可リストを作成しました。開発者はgit branchを承認したが、それは我々の誰もが承認したであろうものだ。チェックはコマンドを検査し、問題がないと判断した。これはまさにチェックの役割である。攻撃は結局成功した。
エージェントが読み取ったすべての指示を正しく判断できるようにするのは、エージェントの能力が向上するにつれて難しくなる問題であり、明確な解決策はない。エージェントが到達できる範囲を制限するという問題は、ずっと前に解決済みです。より有効な方法は、最初の方法を不要にし、エージェントが到達する可能性のある内容を、各ラップトップが個別に保持するリストではなく、後で確認できる成果物として書き留めておくことです。
6本シリーズの次回の記事では、ClawHubの情報窃盗キャンペーンを取り上げます。このキャンペーンでは、マーケットプレイスのランキング脆弱性を悪用して悪意のあるスキルが開発者のマシンに到達し、サンドボックス化されたスキル実行と共有スキルストアが、個人では監査できないレジストリにどのような変化をもたらすのかを検証します。
詳しく見る
- Docker Sandboxでエージェントを安全に実行: 利用を開始するには、 Docker Sandboxesのドキュメントを参照してください。
- セキュリティモデルを理解する: 信頼境界と分離レイヤー、およびデフォルトで分離されているものとされていないものについて。
- キットを使って砂場をカスタマイズしよう: エージェントにツール、認証情報、ネットワークルールを宣言的な成果物として追加する。
- チーム全体のエージェントを管理する: 構造化された監査イベントを備えた、中央集権的に定義されたサンドボックス、ネットワーク、およびMCPポリシーのためのDocker AIガバナンス。
- MCPホラーストーリーズシリーズをお読みください:まず、問題1から始めて、ここで取り上げたエージェント層のリスクを補完するプロトコル層のセキュリティリスクについて理解してください。