検索
ニュース

人が「承認」した無害なコマンドでAIが乗っ取られる コードエディタCursorを襲った“2行の攻撃”「許可リストで安全」神話崩壊

Dockerは、AIコーディングエージェントのトラブル連載第5回を公開した。開発者が承認した無害なコマンドが、書き換えられた環境変数によって攻撃者のコードを実行する手口を取り上げている。

Share
Tweet
LINE
Hatena

 Dockerは2026年8月18日(米国時間、以下同)、AIコーディングエージェントのトラブルを扱う連載「Coding Agent Horror Stories」(コーディングエージェントの恐ろしい話)の第5回を公開した。今回の題材は、AIエージェントを組み込んだコードエディタ「Cursor」の脆弱(ぜいじゃく)性「CVE-2026-22708」だ。

 この脆弱性は、セキュリティ企業Pillar Securityの研究者が2026年1月14日に公表した。Cursorのエージェントを許可リスト付きの自動実行モードで動かしているとき、一部のシェル組み込みコマンドが許可リストに現れないまま、承認を求められることなく実行された。

 READMEや依存パッケージ、「Issue」のコメントなどエージェントの目に触れるテキストに悪意のある指示を仕込んでおけば、そこから環境変数をひそかに書き換えることが可能だ。Cursorはこの脆弱性の深刻度を「High」と評価し、バージョン2.3で修正した。メモリ破壊も権限昇格も関与せず、承認画面で無害なコマンドを承認しただけで、任意のコード実行が成立する。

2行で成立する攻撃

 プログラムは通常、起動時に環境変数から設定を読み込む。「Git」は出力を表示するプログラムを決めるために「PAGER」を参照し、「Python」は「PYTHONWARNINGS」を参照する。これらを変更するのはシェルの組み込みコマンドで、Pillar SecurityはCursorのセキュリティモデルによって暗黙的に信頼されているコマンドとして、「export」「typeset」「declare」を挙げている。組み込みコマンドはディスク上のプログラムではないので、ユーザーに表示されないまま通過した。

 攻撃は2行で成立する。

# こちらは何も表示されずに実行される。承認を求められることはない
export PAGER="open -a Calculator"
# こちらは承認を求められるが、当然のものとして許可してしまう
git branch

 Gitはブランチ一覧の表示方法を決めるためにPAGERを参照し、そこにある攻撃者のコマンドを実行する。Pillar Securityは、許可リストを完全に空にした最も厳しい設定でもこの攻撃が成立したとしている。

 攻撃は2つの段階に分かれる。目に見えない前半部分では、エージェントが読むよう指示されたファイルにユーザーではなくエージェント宛ての指示が含まれており、組み込みコマンドによって静かに環境変数が設定される。

 後半部分では、ユーザーが「git branch」や「python3 script.py」を実行するか、許可リストに従ってエージェントが代わりに実行する。これらは確認の中断を減らすために許可リストに追加するコマンドであり、リストをうまく調整するほどトリガーは確実に引かれる。承認そのものを省く亜種もあり、「~/.zshrc」に行を書き足せば端末を開くたびにコードが実行される。


攻撃の流れ(提供:Docker

 Cursorのドキュメントは現在、許可リストをベストエフォートと説明し、迂回(うかい)が可能だと警告している。Pillar Securityはさらに踏み込み、「エージェントには隔離環境の中でのみ完全なコマンド実行権を与えるべきで、業界は許可リストを廃止すべきだ」と主張している。

 Pillar Securityの報告は2025年8月、修正は2026年1月だった。Cursorはパーサーが分類できないものには承認を必要とする変更を加え、実証された経路をふさいでいる。


攻撃の流れを4コマで表現(提供:Docker

Docker Sandboxesが止められるもの、止められないもの

 AIコーディングエージェントを隔離環境で実行する「Docker Sandboxes」は、エージェントをmicroVM上で動かす。それぞれが独自のカーネル、ファイルシステム、デフォルト拒否のネットワークを持つので、汚染された依存パッケージはホストにも認証情報にも到達できない。このサンドボックスの中では「sudo」を含めて何でも実行でき、迂回すべき許可リストは存在しない。

 同じ攻撃をサンドボックスの中で実行しても侵入は成立し、環境は書き換えられ、「git branch」がトリガーを引き、ペイロードは動作する。ただしペイロードがSSH鍵を探しても、ホームディレクトリは境界の外にあり、サンドボックスの中に「~/.ssh/id_rsa」は存在しない。

 鍵を使うことはできる。サンドボックスは「git push」のような通常作業のためにSSHエージェントのソケットを箱の中に転送しており、中のコードは認証を代行させられるためだ。持ち出せはしないが、動作中は借用できる。これを制限するのはネットワークポリシーで、SSHは接続先のアドレスとポートを明示したルールがなければ接続できない。

 「~/.zshrc」の手口も成立しない。このファイルはホスト側にあり、サンドボックスの中に書かれた汚染されたコピーはサンドボックスと一緒に消える。データの持ち出しも難しく、HTTPとHTTPSはホスト上のプロキシでルールと突き合わされ、それ以外のTCP通信はアドレスとポートを指定したルールが必要で、UDPとICMPは遮断される。


サンドボックス内で攻撃を実行した場合に到達できる範囲(提供:Docker

 Dockerはセキュリティドキュメントで2つの注意点を挙げる。

 1つ目はワークスペースだ。デフォルト(既定)ではホスト上でライブ(同期)状態にあるので、Gitフックや「Makefile」のターゲットには引き続きアクセスできる。そのため、汚染されたフックがあっても「git diff」には表示されない。「--clone」オプションを指定して実行すると、エージェントに独自のコピーが渡される。

 2つ目は共有エージェントスキルストアだ。サポートされているエージェントは、作成時に無効化しない限り、ホスト側の同じストアを読み書き可能でマウントする。ストアを共有する全てのサンドボックスは1つの信頼境界内に位置するので、あるサンドボックス内で変更されたスキルは、次にそれを読み込むサンドボックスへの入力となる。

 ただし、ストア自体はサンドボックスの状態であり、変更されたスキルが単体でホスト上で実行されるわけではないので、リスクはホスト側ではなくサンドボックス間にとどまる。

 Pillar Securityは、4つのコーディングエージェントにおけるサンドボックス脱出に関する報告を公開したが、その手法はサンドボックスの破壊ではなく、内部で書き込まれたファイルを外部のツールが後から信頼してしまうものだった。上記で挙げた2つの注意事項も、それと同じ構造を持っている。

Dockerが推奨するベストプラクティス

 Dockerは、結論の中で「エージェントが何に到達してよいかを、各自のノートPCが持つリストではなくレビュー可能な成果物として書き下す」ことを勧め、以下6つをベストプラクティスとしている。

「export」を他のコマンドと同様に扱う

 次のコマンドが許可リストに載っていてもその動作を変え得る。

許可リストを境界と取り違えない

 ベンダーのドキュメント自体がベストエフォートだと明言している。

最初のコマンドの前に隔離する

 信頼できないとは、自分が書いておらず読んでもいないもの全てを指す。

検証していないコードには「--clone」を使い、共有スキルストアからは除外する

 Gitフックとビルドスクリプトがホスト上で生き続ける。

転送されたSSHエージェントは生きた認証情報だと認識する

 鍵ファイルが手元に残ることは、鍵が使えないことと同じではない。

自分のポリシーを読む

 長い許可リストを伴うデフォルト拒否は、見た目よりもデフォルト許可に近い。

Copyright © ITmedia, Inc. All Rights Reserved.

ページトップに戻る