すべての投稿に戻る
公開日 · 著者 Renaud Deraison

シンボリックリンクはワークスペースを抜け出し、盗る価値のあるものを見つけられなかった

GhostApprovalは、悪意あるリポジトリが6つのAIコーディングアシスタントを騙し、本来留まるべきフォルダの外でファイルを読み書きさせられることを示しました。SSHキーを植え付け、シェルの起動を乗っ取り、開発者自身のマシンでクラウド認証情報を読み取るのです。バグはシンボリックリンクの追跡ミスにすぎません。それが痛手になるのは、エージェントがあなたのシークレットだらけのマシンの上で動いているからです。Bromure Agentic Codingは、その2つ目の事実を変えます。

コーディングエージェントとは、あなたのラップトップでファイルを読み書き するよう招き入れたプログラムです。GhostApprovalは、悪意あるリポジトリが そのプログラムを説き伏せて、線の少し外側——あなたのSSHキー、シェル設定、 クラウド認証情報——に書き込ませたとき、何が起きるかの物語です。バグは 古くて退屈なものです。被害は、エージェントの立っていた場所から 生まれるのです。

2026年7月8日、Wizのリサーチチームは GhostApproval を公開しました。人気のAIコーディングアシスタント6つ——Amazon Q Developer、AnthropicのClaude Code、Augment、Cursor、GoogleのAntigravity、 Windsurf——に、6つの異なる形で見つかった同じ欠陥の報告です。細部は製品 ごとに違いますが、形は同じです。誰かがリンクしたチュートリアルや、同僚に 見てほしいと頼まれたプロジェクトなど、あるリポジトリを開き、コーディング エージェントをそこに向けます。そのリポジトリのどこかに、ファイルではない ファイルがあるのです。

ファイルではないファイル

仕掛けはシンボリックリンク、すなわちファイルのように見えて、実は別の パスを指す道標にすぎないファイルシステムのエントリです。シンボリック リンクは40年来のごく普通のUnixの機能です。そのセキュリティ問題も、 CWE-61としてカタログ化 されているとおり、ほとんど同じくらい古いものです。指す先を確かめずに シンボリックリンクを開くプログラムは、作者が意図しなかったファイルへと 攻撃者に誘導されてしまうのです。

GhostApprovalでは、悪意あるリポジトリが、たとえばproject_settings.json のような無害に見える名前のシンボリックリンクを同梱します。中身は設定では なく、開発者のホームディレクトリ——リポジトリのフォルダのはるか外側——に ある~/.ssh/authorized_keys~/.zshrc~/.aws/credentialsを指す ポインタです。そしてREADMEが、あるいはリポジトリの指示に従うユーザーが、 エージェントに「project_settings.jsonを更新して」と頼みます。 エージェントは行き先を解決しないまま道標に従い、本当のターゲットに 書き込んでしまうのです。

ワークスペース — クローンした repoproject_settings.json設定ファイルに見えて実はシンボリックリンク「project_settings.jsonを更新して」— リポジトリのREADME、エージェントはそれに従うワークスペース境界安全という仮定 — その仮定こそがバグ開発者のホーム (~) — リポジトリの外~/.ssh/authorized_keys~/.zshrc~/.aws/credentials本物のホスト権限 · 本物のクラウド鍵 · ログインごとに走るシェルエージェントはリンクに従うCWE-451 — プロンプトはこれから起きることを偽って伝える本当の標的: ~/.ssh/authorized_keys表示: 「project_settings.jsonを編集? [Yes]」
GhostApprovalの仕組み。クローンしたリポジトリには設定ファイルに偽装したシンボリックリンクが含まれ、ワークスペースの外、開発者のホームディレクトリを指している。エージェントがそれを編集すると、書き込みは~/.ssh/authorized_keys、~/.zshrc、~/.aws/credentialsに着地する。さらに悪いことに、いくつかの製品では確認プロンプトが、これから触れる機微なパスではなく、エージェントが編集を頼まれた無害な名前のほうを表示していた(CWE-451)。

これを単なる小ネタ以上のものにする点が2つあります。1つ目は、ターゲット が何をするかです。~/.ssh/authorized_keysに1行追記すれば、攻撃者の鍵が インストールされ、パスワードなしのSSHであなたのマシンに入れるように なります。~/.zshrcへの書き込みは、ターミナルを開くたびに攻撃者の コマンドを実行します。Augmentのエージェントに至っては、書き込む必要 すらありませんでした。「プロジェクト内のAWSキー」について尋ねられると、 シンボリックリンクをたどって認証情報ファイルまで出て行き、シークレット をチャットに印字したのです。プロンプトは一切出ませんでした。

2つ目は、WizがCWE-451、 ユーザーインターフェースの虚偽表示として分類する、より捉えにくい失敗 です。Claude Codeでは、エージェント自身の内部の推論はそのファイルを シェル設定だと認識していながら、確認ダイアログは「project_settings.json にこの編集を加えますか?」としか尋ねませんでした。人間が危険を捕まえられた はずのただ一つの瞬間が、人間に間違った情報を見せていたのです。Windsurf とAmazon Q Developerはさらに悪く、承認ボタンを表示する前にファイルを ディスクに書き込んでいました。ダイアログは関門ではなく、取り消しの案内 だったのです。攻撃者のSSHキーは、すでに設置済みでした。

その後、ほとんどのベンダーは自らの変種を修正しました。Cursorはv3.0で (CVE-2026-50549)、 Amazon Qはlanguage-server 1.69.0で (CVE-2026-12958)、 GoogleはAntigravity v1.19.6で、Claude Codeはシンボリックリンク解決の 警告で。これは正しい対応であり、アップデートは適用すべきです。しかし 各製品のシンボリックリンク処理へのパッチが直すのは機構のほうであり、 賭け金は元の場所に置かれたままなのです。

賭け金は、エージェントの立つ場所で決まる

これらのペイロードはどれも同じことを前提にしています。開発者のホーム ディレクトリには、到達する価値があるということです。~/.sshには本物の マシンを開く鍵があり、~/.aws/credentialsには生きたクラウドトークンが あり、~/.zshrcはあなたが明日開くシェルで実行される、と。シンボリック リンクは道にすぎません。目的地は、あなたの仕事人生まるごとが載った ラップトップなのです。

コーディングエージェントへの攻撃の大半は、同じ前提の上に立っています。 エージェントは有能でオープンエンドなプログラムであり、信頼できない入力 (リポジトリ、Webページ、パッケージのtarball、ツールの出力)を読み、 あなたの認証情報が数ディレクトリ先の平文ファイルに座っているマシンで 行動します。エージェントをどれだけ堅牢化しても、それはあなたが動かす 他のすべてと、1つのファイルシステムと1つのキーチェーンを共有しています。 攻撃者は新しい道を舗装し続けるでしょう。問題は目的地なのです。

Bromure Agentic Codingは、その目的地を取り除きます。エージェント、それが 生成するシェル、クローンするリポジトリ、その中のあらゆるコードは、 プロファイルごとのLinux VM——ハイパーバイザーがあなたのMacから壁で 隔てた別のマシン——の中で走ります。本物の認証情報は決してそこに入り ません。境界が檻に勝る理由については Bromure Agentic Codingがサンドボックスではない理由 に書きました。GhostApprovalはこの考えの格好の試金石です。業界が頼りに していた唯一の小さな境界であるワークスペースのフォルダを、まさに脱出して みせるからです。

あなたのMac上のエージェント1台のマシン、1つのホームエージェント + クローンしたリポジトリsymlink → ~/.ssh/authorized_keys~/.ssh/authorized_keys本物~/.aws/credentials本物~/.zshrc本物結果攻撃者のSSHキーが設置され、クラウド鍵は読まれ、シェルは乗っ取られる —あなたが日々使うマシンの上で。Bromure Agentic CodingプロファイルごとのVM — 使い捨てエージェント + クローンしたリポジトリsymlink → ~/.ssh/authorized_keys書き込みは起きる~/.ssh/authorized_keysスタブ~/.aws/credentialsスタブ~/.zshrcゲスト結果鍵は使い捨てのゲストに追加され、持ち出された鍵はプレースホルダー —あなたのMacは部屋に入ってすらいない。
同じシンボリックリンクの脱出、2台のマシン。通常の構成では、エージェントは本物の~/.sshや~/.awsのすぐ隣で動くため、リンクをたどれば生きた鍵と、乗っ取る価値のあるマシンに届く。BromureではエージェントはプロファイルごとのVMの中で動く。シンボリックリンクは依然として解決され、書き込みも起きるが、着地するのは使い捨てのゲストであり、そのホームディレクトリにあるのはスタブ——公開インターネット上では何の意味も持たないプレースホルダーのファイル——だけだ。あなたのMacのファイルシステムはハイパーバイザーの線の下にあり、VMにマウントされることは決してない。

同じ脱出を、今度はVMの中でなぞってみましょう。シンボリックリンクは 依然として解決され(Bromureはこの仕掛けを検知も阻止もする必要が ありません)、書き込みは依然として~/.ssh/authorized_keysに着地します。 しかしそのファイルが暮らすのはゲストのホームディレクトリ、あなたの Macへの経路を持たない使い捨てのマシンの上です。攻撃者の鍵が与えるのは、 あなたがやがて捨てるマシン、そもそも外から到達できたためしのないマシン へのログインなのです。

認証情報窃取の変種は、さらに拍子抜けです。乗っ取られたエージェントが シンボリックリンクをたどって~/.aws/credentialsに至り、その中身を チャットに印字しても、読み取るのはスタブ——形式は正しくとも、その鍵 ではどこにも認証できない認証情報ファイル——です。本物のトークンはホスト 上に留まり、ブローカーの背後にあります。ブローカーは、あなたが許可した 外向きの呼び出しの瞬間にだけプレースホルダーを本物のシークレットに 入れ替え、レスポンスからはそれを外して戻します。シークレットを求めて ファイルシステムを漁る依存パッケージや騙されたエージェントが見つける のは、置き物だけなのです。

プロンプト、そして2枚目のネット

BromureはGhostApprovalの2つの鋭い刃に、それぞれ別の層で応じます。

1つ目は確認プロンプトの問題、CWE-451です。エージェントは~/.zshrcを 意味すると知っていながら、ダイアログはproject_settings.jsonと言って いました。Bromureはファイル書き込みのダイアログを廃します。使い捨てVMの 中の書き込みが触れるのは消耗品のディスクであり、承認は要りません。その 代わりBromureは、VMを出て状態を変える呼び出し——git push、データベース のDROP、クラウドのTerminate——という本当の境界に人間を差し込みます。 それらはホスト上で一時停止し、エージェントが書いた要約ではなく、文字 どおりの操作をあなたに見せます。GhostApprovalが破ったのと同じ原則を、 意味のある場所に適用したものです。決定がサンドボックスの外に帰結を持つ 瞬間こそ、人間が本当の呼び出しを見るべき瞬間なのです。

2つ目の刃は、攻撃全体の口火を切る指示です。「project_settings.json を更新して」と告げるREADMEを、モデルは文脈として読み、命令として 従います。Bromureはその信頼できないコンテンツを、まずデバイス上で 読みます。ローカルの分類器が、入ってくるファイル、Webの取得結果、 ツールの出力を、そこにあるべきでない指示が紛れていないか採点し、 エージェントが常任命令として扱うルールファイルには、より厳しい審査を かけます。分類器が取りこぼす言い回しもあるでしょうし、この攻撃は隔離 だけでも打ち破れます。これは1枚目の下に張られた2枚目のネットとして 扱ってください。

線があなたを救わない場所

隔離とは特定の形であり、形には縁があります。

プロファイルは長生きするので、持続化も持続する

~/.zshrcのペイロードは、そのプロファイルのVMの中で次にシェルが 開いたときに実行されます。走る先はホストの鍵を持たず、スタブの 認証情報しかないゲスト、空き部屋の中のシェルですが、それでも走る ことは走ります。あるタスクでそれが気になるなら、新しいプロファイル で実行してください。

マウントしたものは、さらされる

VMはデフォルトではあなたのものを何も持ちません。本物のホストの ディレクトリを意図的にプロファイルへマウントしたり、生きたトークン をゲストに貼り付けたりすれば、シンボリックリンクの脱出はそこに 届きえます。線はあなたのシークレットを外に保ちます。それを中に戻す のは、あなたにしかできない選択です。

ブローカーの範囲は意図して絞る

スタブのおかげでディスク上のファイルは無価値ですが、ブローカーは 依然として、あなたが許可する呼び出しのための本物のトークンを保持 しています。リポジトリを読むだけでよいプロファイルが、それを公開 できるトークンを携えるべきではありません。隔離は爆発を封じ込め、 スコープはその爆発がそもそもどこまで大きくなりうるかを決めるのです。

ワークスペースは間違った壁だった

GhostApprovalは、突き詰めれば、業界が何を境界として扱うことに合意して きたかの物語です。ワークスペースのフォルダ、すなわち「エージェントは プロジェクトディレクトリに留まる」という考えを、どんな道標でも迂回できる デフォルトではなく、セキュリティ特性として扱ってきたことです。 シンボリックリンクそのものは、ベンダーがパッチを当てられる、そして実際に 当てたバグです。境界をフォルダに引けば、どんなシンボリックリンクも、 どんな..も、どんな巧妙なパスもそこから出ないことを、永遠に証明し続ける 羽目になります。ハイパーバイザーに引けば、その問いはもう重要では なくなります。エージェントが脱出するが、あなたのものを一度も持った ことのない使い捨てのマシンだからです。

ベンダーのパッチは適用してください。実在する穴を塞ぐものです。しかし その穴が痛かったのは、エージェントがあなたのラップトップの上、鍵から 1ディレクトリの距離に立っていたからです。エージェントをラップトップの 外に移せば、次の脱出は(必ず来ます)空き部屋に到着します。 Bromure Agentic Codingは無料で、オープンソースで、 今日から使えます。