サイボーグセッション:Claude AI Agent Chrome拡張機能のリバースエンジニアリングと検出
Yosi
脅威インテリジェンス
2026年7月24日

(原文:2026年02月18日)
ローカル実行へのシフト
つい最近まで、「Computer Use Agents(CUA)」は主にサーバーで動作し、データセンター内の仮想マシン上でサンドボックス化されていました。理論上は安全性が高い一方で、このアプローチには大きな問題がありました。
- 検出:Dデータセンタートラフィック(DCH)は、ノイズが非常に多いことで知られています。HTTP Message SignaturesやWeb Bot Authのような暗号化技術によって、このトラフィックを正当化しようとする取り組みは進化しています。しかし、多くのWebサイトは、こうした環境における「検証済み」エージェントと悪意あるスクレイパーを確実に区別できないため、結果として一律にブロックする判断を取りがちです。
- 認証:ユーザーは、外部インフラ上で動作するブラウザやマシンに認証情報を預けることに抵抗を感じていました。
- コスト:ユーザーセッションごとに高可用性の仮想マシンを運用するには、多くのリソースが必要でした。
その結果、業界はユーザーのマシン上で直接動作するローカルWebエージェントへと舵を切りつつあります。これにより、正規ユーザーのIP、Cookie、アクティブなセッションを活用できるようになります。
導入ギャップ:拡張機能 vs. カスタムブラウザ
ローカルエージェント市場は、主に2つのアプローチに分かれています。PerplexityのCometやOpenAIのAtlasのようなカスタムAIブラウザ、そしてManusやClaudeのようなブラウザ拡張機能です。
カスタムブラウザは深い統合を実現できる一方で、導入にはハードルがあります。ユーザーは、普段使っているブラウザをなかなか乗り換えたがりません。さらに、プラットフォーム上の制約も導入を妨げます。たとえばAtlasは現時点でMacのみ対応しており、Windows版の明確なリリース時期は示されていません。
一方、拡張機能の導入はインストールのみで完了するので導入が進んでいます。この勢いは、Chrome Web Storeを見ると明確です。Claude Chrome Extensionは約50万人のユーザーを抱え、Manusも2026年1月時点で急速に10万人に到達しています。AtlasやCometのようなカスタムブラウザのユーザー基盤を検証することはできませんが、拡張機能のインストール数と可視性は、既存ブラウザを置き換えるよりも、拡張して使うことへの強い需要を示しています。
インサイト:「ハイブリッド」セッション
この変化は、ボット検出に新たな概念をもたらします。もはや「ボット vs. 人間」という二元論は成り立ちません。
現在、私たちはハイブリッドセッションを目にするようになっています。正当なユーザーがログインし(人間)、ページへ移動し(人間)、その後、特定のタスクを実行するためにエージェントを起動する(ボット)。セッションIDとIPは同じままですが、入力を制御している主体が、人間と機械の間で切り替わるのです。
CHEQのリサーチチームは、ローカルエージェントのエコシステム全体を継続的に追跡・分析していますが、本記事ではClaude拡張機能を主なケーススタディとして取り上げます。
トラフィックを正しく帰属させ、アプリケーションを保護するには、こうしたケースを区別する必要があります。そのためには、次の課題に焦点を当てる必要があります。
- インストールされているのか?
- 現在実行中なのか?
- このセッション内で過去に実行されたのか?
アーキテクチャ:ブラウザ内CDPとNative Messaging
Claudeを検出する方法を理解するには、まずその権限を理解する必要があります。Claudeは、高レベルのDOM APIのみに依存する一般的な拡張機能とは異なり、より低レイヤーに近い場所で動作します。
ドキュメントと権限リクエストによると、この拡張機能はchrome.debugger APIを活用しています。これにより、開発者がアプリケーションのデバッグに使用するものと同じインターフェースであるChrome DevTools Protocol(CDP)へ直接アクセスできます。CDPを通じて、エージェントは以下を実行できます。
- 標準的なサンドボックス制限の回避:人間のハードウェア入力と区別できない「信頼された」ユーザーイベント(クリックやキーストローク)を合成できます。
- 低レベルシグナルの読み取り:ネットワークリクエスト、コンソールログ、生のアクセシビリティツリーを可視化できます。
- 任意コードの実行:開いている任意のページのコンテキスト内にJavaScriptを注入・実行し、状態を直接操作できます。
重要なのは、このアーキテクチャがブラウザ内で完結していない点です。拡張機能はnativeMessagingという機能を利用し、ローカルのClaude DesktopまたはCLIエージェントとの双方向パイプを確立します。つまり、「頭脳」はブラウザプロセスの外に存在することが多く、ユーザーの認証済み状態(Cookieやローカルストレージ)を共有しながら、CDPコマンドを拡張機能へ送信してセッションを操作します。
このアーキテクチャは、ブラウザを事実上「ヘッドフル」な自動化ドライバーへと変えます。ユーザーにとっては強力な仕組みですが、見るべき場所を知っていれば、非常に可視化しやすいものでもあります。
1. 検出:拡張機能はインストールされているか?
特定の拡張機能がインストールされているかどうかを検出するのはとても難しいです。現代のブラウザは、フィンガープリンティングを防ぐため、Webサイトがインストール済み拡張機能を列挙することを基本的にブロックしています。つまり、ユーザーの拡張機能一覧を取得できるシンプルなJavaScript APIは存在しません。
そこで利用するのがサイドチャネルです。具体的には、拡張機能のmanifest.jsonに含まれる「Web Accessible Resources」を分析します。これは、拡張機能がWebページからの外部アクセスを明示的に許可している特定のファイルです。
私たちは、アクセシビリティツリーに関連する特定のスクリプトリソースを特定しました。
一般的な方法としては、<script>タグでスクリプトを読み込み、onloadイベントを監視する方法が考えられます。しかしこれは危険です。サードパーティコードを自社アプリケーションのコンテキスト内で強制的に実行することになり、予期しない副作用を引き起こす可能性があります。
より安全な方法は、fetch APIを使用することです。対象リソースの取得を試み、Promiseが解決されればファイルが存在する、つまり拡張機能がインストールされていると判断できます。拒否されれば、拡張機能は存在しません。
JavaScript function isClaudeExtensionInstalled() { const extId = "fcoeoabgfenejglbffodgkkbkcdhcgfn"; // Note: The hash 'D39zjmMD' is subject to change in future versions const asset = `chrome-extension://${extId}/assets/accessibility-tree.js-D39zjmMD.js`; return fetch(asset) .then(res => res.ok) .catch(() => false); } // Usage isClaudeExtensionInstalled().then(installed => { console.log("Claude extension installed:", installed); });
2. 検出:エージェントはアクティブか?
インストールされていても、実際に使われているとは限りません。そこで、アクティブな制御を検出するために、DOMの変更に注目しました。
Claudeが操作を開始すると、特定のUIオーバーレイ、つまりユーザーが停止できる「Stop」ボタンが注入されます。このインターフェースを描画するために、拡張機能はid=”claude-agent-stop-container”のコンテナ要素をdocument bodyへ直接追加し、遷移処理のためにid=”claude-agent-animation-styles”の専用スタイルブロックも追加します。
Chrome DevToolsで確認すると、エージェントの痕跡がページ構造に直接注入されていることが明確に分かります。
これらの要素を必要なタイミングで単純にチェックすることもできますが、より適切なのはDOMをリアルタイムで監視する方法です。Mutation Observerを使えば、エージェントが制御を開始した瞬間(注入)と、制御を手放した瞬間(削除)を検出できます。
JavaScript
// Monitor the DOM for the agent's "Stop" button appearing or disappearing const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { // Detect Agent Start mutation.addedNodes.forEach((node) => { if (node.id === 'claude-agent-stop-container') { console.log('Claude Agent started running.'); } }); // Detect Agent Stop mutation.removedNodes.forEach((node) => { if (node.id === 'claude-agent-stop-container') { console.log('Claude Agent stopped.'); } }); }); }); // Start observing the body for direct children changes observer.observe(document.body, { childList: true });
3. 検出:フォレンジック上の痕跡
エージェントがタスクを完了すると、「Stop」ボタン、つまりコンテナ要素はDOMから削除されます。しかし、拡張機能は完全には後片付けを行いません。
Claudeが操作を開始すると、特定のUIオーバーレイ、つまりユーザーが停止できる「Stop」ボタンが注入されます。このインターフェースを描画するために、拡張機能はid=”claude-agent-stop-container”のコンテナ要素をdocument bodyへ直接追加し、遷移処理のためにid=”claude-agent-animation-styles”の専用スタイルブロックも追加します。
function hasClaudeAgentRun() { return !!document.getElementById('claude-agent-animation-styles'); }
> 開発メモ: ここでは分かりやすさのために具体的なIDを使用していますが、本番環境向けの検出ルールでは、将来の拡張機能アップデートによる軽微な名称変更に耐えられるよう、[id^=”claude-agent-“]のようなワイルドカードセレクタを使用するのが望ましいでしょう。
まとめ
「ハイブリッドセッション」という概念は、いよいよ現実に運用され始めています。セッションを単純な二元論で捉えることはますます難しくなっています。正当なユーザーセッションの中に、自動化タスクがシームレスに組み込まれる可能性が現実のものになっているからです。
ローカルエージェントの痕跡、具体的にはWeb Accessible Resourcesや永続的なDOMアーティファクトを分析することで、ユーザーがブラウジングしているのか、エージェントが実行しているのかをより正確に区別し、アクティビティを適切に帰属させることができます。こうしたツールがさらに普及するにつれ、入力の発信源を特定することは、精度の高いアナリティクスとセキュリティに不可欠なステップとなるでしょう。



