ブラウザ拡張ウォレット:全サイト権限とサイレント更新のリスク
6つのウォレット拡張の現行ビルドを取り出して manifest を読みました。6つすべてが閲覧する全サイトを読み、更新は確認なしで届きます。交換にとって何を意味するか。
ウォレット拡張はインストール時に「すべてのウェブサイトのデータを読み取り、変更する」権限を求めます。これはダークパターンではなく仕組みです。拡張がプロバイダーオブジェクトを全ページに注入しなければ、サイトの交換ボタンから見つけてもらえません。副作用として、同じソフトが二つの能力を同時に持ちます。フォームに貼ったアドレスを読むこと、そしてサイトの求めに応じて署名すること。2026-10-28、私たちは Google 自身の更新エンドポイントから主要6ウォレットの現行ビルドを取得し、展開して manifest を読みました。本稿はそれらのファイルが実際に何を宣言しているか、なぜ権限ダイアログより更新経路のほうが疑わしいのか、そして当社のような交換サイトに何ができて何ができないかを書きます。
ウォレット拡張機能とは何か
取得した6件はすべて Manifest V3 です。V3 は問題の形を変えました。V3 ウォレットは常駐ページを持たない service worker、document_start(サイト自身の JS より前)で注入されるコンテンツスクリプト、そしてどのオリジンに触れてよいかを決める host 権限でできています。コンテンツスクリプトは隔離ワールドで動くためページの変数は直接読めませんが、DOM の読み書きはでき、アドレス入力欄を書き換えるには十分です。署名は別の明示的な手順で、ウォレットが自前のウィンドウを開き利用者が承認します。忘れられがちなのは「読む」側の権限で、これはインストール時に一度だけ、多くの人が一秒で閉じるダイアログで与えられます。参考までに MetaMask の現行 manifest は cookies、webRequest、identity、offscreen を含む11の権限を要求し、clipboardRead を任意権限に持っています。
2026-10-28 06:02 UTC に測った権限表
読んだのは MetaMask 13.54.0.0、Phantom 26.35.0、Rabby 0.94.13、Keplr 0.13.53、Trust Wallet 26.42.4、OKX Wallet 4.21.0 です。6件すべてが全 http/https オリジンへのアクセスを宣言しています。MetaMask はさらに ws、wss、file、localhost:8545 を加え、任意のウェブサイトからのメッセージを受け付ける唯一の存在でした(externally_connectable の拡張 ID がワイルドカード)。Rabby は最も粗い all_urls、Keplr は all_urls に document_start でコンテンツスクリプトを注入、Trust Wallet は clipboardWrite と gcm、OKX は全サイトに加えて solscan.io、twitter.com、x.com にコンテンツスクリプトを固定しています。パッケージは 16.4 MB〜54.7 MB、ファイル数 103〜1,187、展開後の JS は 15.5 MB〜92.5 MB。最後の数字が攻撃面の正直な尺度です。数十メガバイトの第三者のコードが、開くすべてのページへの常設権限を持ち、他人によって更新されます。
サイレント更新と、crx_id が守るもの・守らないもの
CRX3 は小さな protobuf ヘッダーと zip の組み合わせです。6件すべて同じ形で、RSA 署名証明2つ、ECDSA 証明1つ、そして16バイトの crx_id を持つ signed_header_data がありました。この id の16進数を a〜p の文字に写すと、ストアで見る32文字の拡張 ID になります。6件すべて一致することを確認しました。つまり鍵は ID に結び付き、他人がその ID のビルドを配ることはできません。しかし公開者は何でも配れ、Chrome は誰にも確認せずインストールします。チェックは先ほど使ったのと同じ公開エンドポイントに対してバックグラウンドで走り、ブラウザのバージョンが引数で渡され、新しいコードは次回のページ読み込みで有効になります。読むべき変更履歴も同意ボタンもありません。だから実際の事故は一層下、依存関係で起きます。@solana/web3.js は 1.95.6 が 2024-12-03 15:10:07 UTC、1.95.7 が 15:20:23 に公開され、どちらも今は registry の版一覧から消え、正常な 1.95.8 は 20:25:40 に登場しました。5時間15分です。@ledgerhq/connect-kit は 2023-12-14 に 1.1.5 が 08:49:04、1.1.6 が 09:44:57、1.1.7 が 10:37:24、正常な 1.1.8 が 13:18:35 で、4時間半。どちらも窓は数日ではなく、自動インストールが版を取り込むまでの時間でした。
交換に必要なもの、拡張がなおできること
ここで当社の製品形状が効いてきます。VeilSwap の注文は5つの項目だけです。売る資産、買う資産、数量、受け取りアドレス、返金アドレス。アカウントもメールもウォレット接続も署名もありません。フロントエンドで window.ethereum、WalletConnect、wagmi を grep しても0件です。フローのどこもウォレットに何も要求しないからです。これで最大のリスク種——読まずに押す承認ダイアログ——は消えます。ただし「読む」権限は消えません。ウォレット拡張は veilswap.io でも document_start で動き、アドレス欄を見られます。アドレス形式とチェックサムは注文作成時にサーバー側で検証され、打ち間違いは止めますが、形式の正しい差し替えは止めません。規模感として 06:04 UTC の実測見積り:100 USDT-TRC20 が 0.14408925 XMR、5,000 が 8.06917242 XMR。1 XMR あたり 694.01 対 619.64 USDT で、12% の差は注文ごとの固定費用であり、ウォレットが関与する数値ではありません。1 XMR は 589.282718 USDT、0.05 BTC は 6.54643747 XMR(130.92875 XMR/BTC、1 BTC 約 77,154 ドル)。カタログは 520 資産・73 ネットワーク。 (XMR→USDT 出口ルート)
六つの行動と、三つの誤解
第一に、ウォレット専用のブラウザプロファイルを一つ用意し、交換はウォレット拡張を入れていないプロファイルで行う。アドレスはコピー&ペーストで行き来すれば十分です。第二に、拡張の管理画面で各ウォレットのサイトアクセスを「クリック時」か短い許可リストにし、更新のたびに見直す。第三に、実際の資金を動かす前に、インストール済みの版とストアの表示を突き合わせる。上に挙げた版は 06:02 UTC に配信されていたもので、手元の版とは限りません。第四に、シードフレーズを求めるものは表示が何であれ攻撃として扱う。ウェブのフローに必要ありません。第五に、金額に見合うならハードウェアで署名し、アドレスはブラウザではなく端末の画面で読む。第六に、更新で権限が増えたら、確認を押すのではなく削除して入れ直す。三つの誤解:ストア審査は悪意ある更新を防ぎません(更新審査は初回より軽く、上の6件はそれぞれ 233、230、64、31、234、392 個の JS ファイルを抱えています)。シークレットモードは砂場ではありません(明示的に許可したときだけ拡張は動き、動けばそのページも読みます)。そして財布を減らしてもリスクは線形には下がりません。全サイト権限は各拡張が独立に持っているからです。
短くまとめます。ブラウザウォレットはハードウェア機器としてのウォレットではなく、ページを読み、ついでに鍵を持つプログラムで、公開鍵の管理権を持つ者によって静かに差し替えられます。交換にそれは要りません。注文に必要なのはアドレスと金額だけです。接続と署名を求めるサイトは、取引が必要とする以上のものを求めています。財布は一つのプロファイルに閉じ込め、交換は別のプロファイルで行い、アドレスはコピー元で一文字ずつ確認する。読んだことのない 92 MB のコードを信じるより、ずっと安い要求です。