:visited のプライバシー保護を強化

Kyra Seevers
Kyra Seevers

公開日: 2025 年 4 月 2 日

リンクをクリックするとどうなりますか?紫色に変わります。

インターネットの黎明期から、サイトは CSS :visited セレクタを使用して、ユーザーが以前にクリックしたリンクにカスタム スタイルを適用してきました。:visited セレクタを使用すると、サイトのユーザー エクスペリエンスを向上させ、ユーザーがウェブをナビゲートするのを支援できます。ただし、アクセスしたリンクのカスタマイズ性が向上するにつれて、セキュリティ研究者によって発見される攻撃の数も増加しています。

こうした攻撃により、ユーザーがアクセスしたリンクが明らかになり、ウェブ閲覧アクティビティの詳細が漏洩する可能性があります。このセキュリティ問題は 20 年以上にわたってウェブを悩ませてきました。ブラウザは、このような履歴検出攻撃を軽減するためにさまざまな暫定的な対策を講じてきました。これらの緩和策によって攻撃は遅くなりますが、排除されるわけではありません。

Chrome 136 以降、Chrome はこのような攻撃を無効にする最初の主要なブラウザです。これは、:visited リンク履歴をパーティショニングすることで実現されます。

以前にアクセスしたリンクを表示するには、ブラウザが過去にアクセスしたページを追跡する必要があります。これを :visited 履歴と呼びます。CSS :visited セレクタを使用して、アクセス済みのリンクと未アクセスのリンクのスタイルを変更できます。

:visited {
  color: purple;
  background-color: yellow;
  }

これまで、:visited の履歴はパーティショニングされていませんでした。つまり、:visited セレクタを使用して :visited 履歴を表示できる場所に制限はありませんでした。リンクをクリックすると、そのリンクを表示しているすべてのサイトで :visited と表示されます。これは、攻撃者がユーザーの閲覧履歴に関する情報を漏洩させる原因となった設計上の根本的な欠陥でした。

次の例をご覧ください。ユーザーがサイト A でブラウジング中にリンクをクリックしてサイト B に移動します。このシナリオでは、サイト B が :visited の履歴に追加されます。後で Site Evil にアクセスすると、Site B へのリンクも作成されます。パーティショニングがないと、Site Evil でリンクをクリックしていなくても、Site B へのリンクが :visited として Site Evil に表示されます。その後、Site Evil はセキュリティ エクスプロイトを使用して、リンクが :visited としてスタイル設定されているかどうかを把握し、ユーザーが過去に Site B にアクセスしたことを把握して、ブラウジング履歴に関する情報を漏洩させます。

パーティショニング前は、リンクをクリックすると、

ユーザーが site-a.com のページにいて、site-b.com へのリンクが表示されている。

そのリンクが表示されるすべてのサイトで「:visited」と表示されます。

同じ site-a.com が site-evil.com の横に表示されます。どちらのページにも site-b.com への同じリンクが表示され、訪問済みとしてスタイル設定されています。

パーティショニングは、このサイトから以前にクリックしたリンクのみを訪問済みとして表示することで、閲覧履歴を保護します。以前にこのサイトを操作したことがない場合は、そのリンクは :visited としてスタイル設定されません。

パーティショニングを有効にした前述の例について考えてみましょう。サイト A でブラウジング中にリンクをクリックしてサイト B に移動すると、「サイト A + サイト B」の組み合わせが :visited 履歴に保存されます。これにより、Site Evil にアクセスしたときに、Site B へのリンクが :visited として表示されなくなります。これは、Site A + Site B のエントリ(リンクを最初にクリックしたコンテキスト)の両方の部分と一致しないためです。Site Evil には閲覧履歴が表示されないため、エクスプロイトを悪用することはできません。そのため、ブラウザの履歴は安全です。

パーティショニング後にリンクをクリックすると、次のようになります。

ユーザーが site-a.com のページにいて、site-b.com へのリンクが表示されている。

:visited として表示されるのは、以前にクリックした場所に限られます。

同じ site-a.com が site-evil.com の横に表示されます。両方のページに site-b.com への同じリンクが表示されますが、site-a.com のリンクのみが訪問済みとしてスタイル設定されます。

簡単に説明すると、パーティショニングとは、リンクがクリックされた場所に関する追加情報とともにリンクを保存することを指します。Chrome では、リンク URL、トップレベル サイトフレーム オリジンです。パーティショニングを有効にすると、:visited 履歴は、どのサイトでもクエリできるグローバルなリストではなくなります。代わりに、:visited 履歴は「パーティショニング」され、最初にそのリンクにアクセスしたコンテキストで分割されます。

リンク URL、トップレベル サイト、フレームのオリジンを介した情報フローを表示します。

インターネットを閲覧していると、同じサイトの異なるサブページに移動するリンクをたくさんクリックすることがあります。たとえば、さまざまな種類の金属を調べる場合は、「chrome」と「brass」の Site.Wiki ページにアクセスします。

パーティショニングを厳密に実装すると、ゴールドの Site.Wiki ページのユーザーには、クロムと真鍮のページへのリンクが :visited として表示されなくなります。これは、ユーザーが、ゴールドの Site.Wiki ページと一致しない最上位サイトからこれらのページのそれぞれをクリックしたためです。

ユーザーが metals.com から site.wiki のリンクをいくつかクリックしても、クリック元が metals.com であるため、リンクは「訪問済み」としてスタイル設定されません。

パーティショニングのプライバシーとセキュリティ保護を維持しながら、このシナリオでのユーザー エクスペリエンスを改善するために、セルフリンクのカルバアウトを導入しました。つまり、サイトは、このコンテキストでこれらのリンクが以前にクリックされていなくても、独自のサブページを :visited として表示できます。サイトには、ユーザーがサブページにアクセスしたかどうかをトラッキングする他の方法があるため、セルフリンクの導入によってこれらのサイトに新しい情報が提供されることはありません。パーティショニングでは、クロスサイト トラッキングから保護し、同一オリジン ポリシーを適用します。ただし、これはサイト独自のサブページへのリンクにのみ適用されます。サードパーティのサイトへのリンクやサードパーティの iFrame 内のリンクは、この例外には該当しません。

「セルフリンク」の除外後:

同じサイトのサブページであるセルフロールは、訪問済みとしてマークされるようになりました。

実装ステータス

:visited のセキュリティとプライバシーに関するこれらの改善は、Chrome バージョン 136 以降で利用できます。Chrome は、ユーザー向けにこれらの保護機能を実装した最初のブラウザです。

意見交換とフィードバックの提供