無音オーディオがBluetoothを切るとき — AliExpressのWebAudioフィンガープリンティング
無音オーディオがBluetoothを切るとき — AliExpressのWebAudioフィンガープリンティング
音ひとつ鳴っていないのに、ヘッドホンがスマホへ戻らない。これはユーザーを識別しようとする意図的な追跡なのか、それともフィンガープリンティングのコードが雑に書かれた結果として漏れ出た副作用なのか — そしてなぜその区別が、当のユーザーには何の慰めにもならないのか。
導入
ある開発者が奇妙な症状を追ううちに、ウェブ追跡産業の内実を露わにしてしまった。彼のBluetoothマルチポイント対応ヘッドホンは本来、PCとスマートフォンに同時接続され、PCから音が出ればPCを優先し、音が止めばスマホへ戻るはずだった。ところがある時からヘッドホンがスマホへ切り替わらなくなった。PC側では何の音も鳴っていないのに、オーディオ経路がずっと掴まれたままだったのである。犯人を追い詰めた末に彼が行き着いたのは、ブラウザに開きっぱなしにしていたAliExpressのタブだった。
laserphileブログに掲載されたこの調査記録(2026年8月)によれば、AliExpressのページは collina.js と fireyejs.js という二つの難読化されたスクリプトを読み込み、これらが画面に見えない AudioContext オブジェクトを生成してブラウザのフィンガープリント(指紋)を収集している。問題は、このオーディオグラフが音量ゼロで無音のまま再生されつつも、ブラウザとオペレーティングシステム(OS)のオーディオ出力経路を活性状態のまま掴み続け、ヘッドホンが別の機器へ切り替われなくする点にある。Hacker News(item 49372583)の議論は、この発見をめぐって「意図された追跡なのか、それとも雑なフィンガープリンティングの事故なのか」で割れた。本稿はまずそのメカニズムを正確に押さえ、次にこうした密やかなフィンガープリンティングがなぜ存在するのか、その系譜と誘因を掘り下げ、最後にユーザーの防御とプラットフォーム規制のあいだのトレードオフを検討する。
音のないオーディオが機器を掴むメカニズム
著者が復元したオーディオグラフの構造はこうだ。ノコギリ波オシレーター(Sawtooth oscillator)が信号を生成し、その信号が解析ノード(AnalyserNode)を経てスクリプト処理ノード(ScriptProcessorNode)へ流れ、ゲインノード(GainNode)で音量がゼロに抑え込まれたのち、最終的に AudioContext.destination — すなわち実際のオーディオ出力 — に接続される。肝心なのは最後の接続である。著者の表現を借りれば、「グラフをdestinationに接続すると、最終音量がゼロであってもブラウザはそのグラフを能動的に処理する(actively process)」。音量がゼロなので人の耳には何も聞こえないが、ソフトウェアの観点からは紛れもなく「再生中のオーディオストリーム」が存在しているのだ。
まさにこの点で物理的な副作用が生じる。マルチポイント対応ヘッドホンは、接続された複数の機器のうち実際にオーディオを出力している機器を優先する。PCのブラウザが音量ゼロのグラフを休みなく回しているあいだ、OSから見ればPCは依然として「音を出している機器」である。だからPCのBluetoothオーディオ経路が活性のまま維持され、ヘッドホンはスマートフォンへ戻る理由を見つけられない。著者が指摘するように、ブラウザのタブミュート(tab mute)機能もこの状況では無力だ。タブミュートは <audio> や <video> といった慣習的なメディア要素を対象に動作するが、ここにはそうした要素がそもそも存在しないからである。WebAudio APIでプログラムが直接合成した音には、ブラウザが用意した通常の制御装置が効かない。
著者がこの密やかなグラフをどう突き止めたかも、この事件の核心である。彼はページ内でオーディオ・ビデオ要素や play() の呼び出しを探したが、一件も見つからなかった。そこでアプローチを変え、AudioContext のコンストラクタそのものをラップ(wrapping)してコンテキストが生成される瞬間を記録し、AudioNode.prototype.connect() をラップしてノードがどこへ接続されるのかを追跡した。この計装(instrumentation)によって、メディア再生の呼び出しはゼロ件なのに、生きて動いている AudioContext が二つも回っていることが明らかになった。つまり、目に見える再生ボタンもメディアタグも一切ないのに、音を合成するパイプラインがバックグラウンドで常時稼働していたのである。
そうして捕まえられたオーディオグラフが実際に集めているのは、音ではなく身元である。著者によれば、このフィンガープリント収集器はオーディオ処理の特性だけでなく、canvasのレンダリング結果、WebGLデータ、画面サイズ、デバイスメモリ、ブラウザのプラグイン一覧、WebRTCの挙動、パフォーマンスタイミング(performance timing)、ユーザーのインタラクションイベントまでも一緒に掻き集める。オーディオフィンガープリントは、この総合フィンガープリントの一軸にすぎない。Hacker Newsの議論では、この副作用がヘッドホンに限られないという証言が相次いだ。補聴器がBluetoothストリームの開始とともに周囲の音を絞ってしまうという指摘、車載インフォテインメントが音声コマンドモードへ誤作動するという指摘、マルチポイント接続全般が撹乱されるという指摘が出た(いずれもHNの議論参加者の経験談を意訳したものである)。音のないコードの一片が、ユーザーの物理的な機器の挙動を現実に変えてしまっていたわけだ。
なぜこんなコードが存在するのか — フィンガープリンティングの系譜と密やかさ
WebAudioフィンガープリンティングは突然現れた手法ではない。その系譜はcanvasフィンガープリンティングまで遡る。同じ絵を描けと命じても、GPU、グラフィックドライバ、フォントレンダリングエンジン、アンチエイリアスの方式が機器ごとに微妙に異なり、結果のピクセルに機器固有の偏差が残る。オーディオフィンガープリンティングは、この発想を音の領域へ移したものだ。同一のノコギリ波を生成して処理させると、オーディオスタックの浮動小数点演算とハードウェア・ソフトウェアの組み合わせに応じてわずかに異なる出力が生まれ、その差がブラウザと機器を識別する安定した信号になる。クッキーのように消せる状態を仕込まなくても機器を再識別できる、いわゆる無状態(stateless)識別子である。
ここでこの事件の技術的な皮肉が浮かび上がる。Hacker Newsで複数の参加者が指摘したように、オーディオフィンガープリンティングは本来 OfflineAudioContext で実装するのが定石である。オフラインコンテキストはリアルタイムより速く(faster-than-realtime)計算を終え、スピーカーへは何も出力しない。フィンガープリント値だけが必要なら、スピーカー経路に手を触れる理由はまったくないということだ。ところがAliExpressのスクリプトは通常の AudioContext を使い、それを実際の出力destinationに接続した(HNの議論で出た分析を意訳)。フィンガープリントを取るのに必要でもない実出力への接続こそが、マルチポイントを壊した原因なのである。だから「意図的な妨害なのか」という問いに、多くの論者が「それよりも雑に書かれたフィンガープリンティングコードの副作用である可能性が高い」と見たのだ。
意図が何であれ、こうしたコードが繁茂する構造的な誘因は明白だ。ブラウザ各社がサードパーティクッキーを撤廃し、Appleの ITP(Intelligent Tracking Prevention)のような防御が強化されるほど、広告・追跡産業はクッキーに頼らずとも個人を繋ぎ合わせられる無状態識別子に渇望する。フィンガープリンティングはその需要への正確な答えだ。しかもフィンガープリントは広告ターゲティングだけでなく、不正取引対策(anti-fraud)やリスク管理にも使われる — fireyejs という名前そのものが、セキュリティ・リスクコントロールの系譜を想起させる。広告とセキュリティという二つの正当化の論理が重なる地点で、常時フィンガープリンティングは「合理的な防御」という外皮をまとう。
もっとも問題含みなのは、この手法の密やかさである。マイクやカメラにアクセスするにはブラウザが明示的な権限プロンプトを出すが、WebAudioで音を合成するには何の権限も要らない(HNの議論で繰り返し指摘された点)。しかも今回のように音量ゼロで回せば、ブラウザのタブにスピーカーのアイコンすら表示されない。ユーザーが「このサイトが音を出している」という事実を認知する窓口がそもそもないのだ。ここにアプリ対ウェブの構図が重なる。AliExpressはアプリのインストールを執拗に勧めるが、アプリの中ではユーザーが追跡を観測したり遮断したりする手段がウェブよりはるかに少ない。逆説的に、ウェブは広告ブロッカーや拡張機能、開発者ツールでこうしたコードを捕捉できる、まだしも開かれた空間である(HNの議論を意訳)。一方で、この特定のフィンガープリンティングがFirefoxでは通用しないという証言もあった。ある参加者は、Firefoxの既存の防御がこのフィンガープリント収集を無力化するとして、ritter.vgの技術分析を根拠に挙げた(HNの議論を意訳)。同じコードがブラウザによって異なる挙動をするという事実は、防御が標準ではなく個々のブラウザのポリシー選択に委ねられていることを示している。
ユーザーの防御とプラットフォーム規制のトレードオフ
では、ユーザーには何ができるのか。もっとも直接的な処方は著者が示したものだ。彼はuBlock Originのフィルタルール二行で問題の二つのスクリプトを遮断し、それでもAliExpressのホームページが正常に動作することを確認した。これは重要な実測である — フィンガープリンティングのスクリプトを止めてもショッピング機能そのものは無傷だという事実は、そのコードがユーザー体験のためではなく、ユーザーを観測するためのものだという傍証になる。より広くは、Firefoxのフィンガープリンティング抵抗(resistFingerprinting)機能、ブラウザプロファイルの分離、追跡が激しいサイトは別のコンテナで開く習慣が防御線になる。ただしここには明確なトレードオフがある。強いフィンガープリンティング防御や広範なスクリプト遮断は正常なサイトを壊す危険を伴い、大半のユーザーはuBlockのフィルタを手ずから書いたり、開発者ツールで AudioContext を計装したりする能力も意思も持たない。個人による防御は、少数の技術ユーザーにのみ実効的な解にとどまる。
そこで視線はプラットフォーム、すなわちブラウザ自身へと向かう。もっとも自然な要求は「無音のオーディオであっても常時再生中ならインジケーターを出すか、権限を問おう」というものだ。だがこの処方にもトレードオフがある。WebAudioはブラウザゲーム、ウェブベースのシンセサイザーやDAW、アクセシビリティツールが正当に使うAPIである。すべての AudioContext 生成に権限プロンプトを掛ければ、正常なアプリケーションの体験が損なわれ、プロンプト疲れ(prompt fatigue)によってユーザーは結局何も考えずに許可を押すようになる。より精緻なアプローチは、フィンガープリンティングで漏れ出る情報の総量そのものを制限することだ — オーディオ・canvas・WebGLの出力に微細なノイズを混ぜたり、一つのサイトが抽出できる識別エントロピーに予算(privacy budget)を課したりする方式である。これは個々のAPIを塞ぐより根本的だが、標準化と合意に長い時間がかかり、ブラウザごとに採用の速度も異なる。
エンジニアの立場から見ると、この事件が与える教訓は少し異なる質感を持つ。フィンガープリンティングのように密やかに設計された計算でさえ、システムの別の層で観測可能な副作用として漏れ出るという点だ。destinationへの接続ひとつが、Bluetooth切り替えという物理現象へ波及して、結局は正体を暴かれた。観測可能性(observability)は防御者の武器であり、同時に雑な追跡者の弱点である。そして防御の成否がブラウザのポリシーに左右されるという事実 — Firefoxでは通用しなかったという証言 — は、ユーザーがどのクライアントを使うかがそのままプライバシーの水準を決めるという現実を、あらためて確認させる。
結論
これは意図された追跡なのか、副作用なのか。技術的な証拠は後者へと傾く。フィンガープリント値だけが必要ならスピーカーに手を触れる理由はないのに、実出力へ接続した雑さがマルチポイントを壊した。しかしユーザーの立場から見れば、その区別は慰めにならない。常時回り続ける無音のフィンガープリンティングは、意図したか否かにかかわらずすでにユーザーを識別していたのであり、ただ今回はヘッドホンがスマホへ切り替わらないという物理的な症状として、偶然その正体を露わにしたにすぎない。我々が感知できない無数のサイトで、同じ計算が何の副作用もなく静かに回っているだろう。
この事件が残す本当の問いは、個々のスクリプトをどう遮断するかではない。権限プロンプトも、マイク・カメラのようなアクセス制御もなしに、ブラウザが任意の身元信号を抽出できるよう放置されたこのウェブのデフォルトを、我々はいつまで正常だと受け入れるのか、である。今すぐできることはある — 追跡の激しいサービスはアプリではなくウェブで開き、広告ブロッカーとブラウザ分離を有効にし、プライバシーをデフォルトに据えるブラウザを選ぶこと。だが少数の技術ユーザーが個別に防御に成功することと、ウェブそのものがユーザーをみだりにフィンガープリントできないよう標準が変わることは、まったく別の問題だ。あなたの機器は今この瞬間、あなたの知らない音を立てていないと、確信できるだろうか。
出典: