キャッシュをパーティショニングすることでセキュリティとプライバシーを確保

一般に、キャッシュ保存によってデータを保存することでパフォーマンスが向上するため、同じデータに対する今後のリクエストを迅速に処理できます。たとえば、ネットワークからキャッシュに保存されたリソースにより、サーバーへのラウンド トリップを回避できます。計算結果をキャッシュに保存することで、同じ計算を行う時間を省略できます。

Chrome では、このキャッシュ メカニズムはさまざまな方法で使用され、HTTP キャッシュはその一例です。

Chrome の HTTP キャッシュの現在の仕組み

バージョン 85 では、Chrome はネットワークから取得したリソースをキャッシュに保存し、それぞれのリソース URL をキャッシュキーとして使用します。(キャッシュキーは、キャッシュに保存されたリソースを識別するために使用されます)。

次の例は、1 つの画像が 3 つの異なるコンテキストでキャッシュに保存され、処理される方法を示しています。

キャッシュキー: https://x.example/doge.png
キャッシュキー: { https://x.example/doge.png }

ユーザーが、画像(https://x.example/doge.png)をリクエストするページ(https://a.example)にアクセスした。画像がネットワークからリクエストされ、https://x.example/doge.png をキーとしてキャッシュに保存される。

キャッシュキー: https://x.example/doge.png
キャッシュキー: { https://x.example/doge.png }

同じユーザーが別のページ(https://b.example)にアクセスし、同じ画像(https://x.example/doge.png)がリクエストされます。ブラウザは HTTP キャッシュをチェックして、画像 URL をキーとして使用し、このリソースがすでにキャッシュに保存されているかどうかを確認します。ブラウザはキャッシュで一致するものを検出すると、リソースのキャッシュ バージョンを使用します。

キャッシュキー: https://x.example/doge.png
キャッシュキー: { https://x.example/doge.png }

画像を iframe 内から読み込んでも構いません。ユーザーが iframe(https://d.example)を使用している別のウェブサイト(https://c.example)にアクセスし、iframe が同じ画像(https://x.example/doge.png)をリクエストしても、キャッシュキーはすべてのページで同じため、ブラウザでキャッシュから画像を読み込むことができます。

このメカニズムは、長い間、パフォーマンスの観点から適切に機能してきました。ただし、ウェブサイトが HTTP リクエストへの応答にかかる時間から、ブラウザが過去に同じリソースにアクセスしたことが明らかになり、ブラウザがセキュリティやプライバシーの攻撃にさらされます。たとえば、次のような攻撃です。

  • ユーザーが特定のサイトにアクセスしたかどうかを検出する: 攻撃者は、特定のサイトまたはサイトのコホートに固有のリソースがキャッシュにあるかどうかを確認することで、ユーザーの閲覧履歴を検出できます。
  • クロスサイト検索攻撃: 攻撃者は、特定のウェブサイトで使用されている「検索結果なし」の画像がブラウザのキャッシュにあるかどうかをチェックすることで、ユーザーの検索結果に任意の文字列が含まれているかどうかを検出できます。
  • クロスサイト トラッキング: キャッシュを使用して、クロスサイト トラッキング メカニズムとして Cookie に似た識別子を保存できます。

これらのリスクを軽減するため、Chrome 86 以降では HTTP キャッシュがパーティショニングされます。

キャッシュ パーティショニングは Chrome の HTTP キャッシュにどのように影響しますか?

キャッシュ パーティショニングでは、リソース URL に加えて新しい「ネットワーク分離キー」を使用して、キャッシュに保存されるリソースにキーが設定されます。ネットワーク分離キーは、トップレベル サイトと現在のフレームサイトで構成されます。

前の例に戻り、さまざまなコンテキストでキャッシュ パーティショニングがどのように機能するかを確認してください。

キャッシュキー { https://a.example, https://a.example, https://x.example/doge.png}
キャッシュキー: { https://a.example, https://a.example, https://x.example/doge.png }

ユーザーがページ(https://a.example)にアクセスし、そこで画像(https://x.example/doge.png)がリクエストされます。この場合、画像がネットワークからリクエストされ、https://a.example(トップレベル サイト)、https://a.example(現在のフレームサイト)、https://x.example/doge.png(リソース URL)からなるタプルをキーとして使用してキャッシュに保存されます。(リソース リクエストがトップレベル フレームからの場合、ネットワーク分離キーのトップレベル サイトと現在のフレーム サイトは同じになります)。

キャッシュキー { https://a.example, https://a.example, https://x.example/doge.png}
キャッシュキー: { https://b.example, https://b.example, https://x.example/doge.png }

同じユーザーが別のページ(https://b.example)を訪問し、同じ画像(https://x.example/doge.png)がリクエストされました。前の例では、同じ画像が読み込まれていますが、キーが一致しないためキャッシュ ヒットにはなりません。

イメージがネットワークからリクエストされ、https://b.examplehttps://b.examplehttps://x.example/doge.png で構成されるタプルをキーとして使用してキャッシュに保存されます。

キャッシュキー { https://a.example, https://a.example, https://x.example/doge.png}
キャッシュキー: { https://a.example, https://a.example, https://x.example/doge.png }

ユーザーが https://a.example に戻りますが、今回は画像(https://x.example/doge.png)が iframe に埋め込まれています。この場合、キーは https://a.examplehttps://a.examplehttps://x.example/doge.png を含むタプルであり、キャッシュ ヒットが発生します。(なお、トップレベル サイトと iframe が同じサイトの場合、トップレベル フレームでキャッシュされたリソースを使用できます。

キャッシュキー { https://a.example, https://a.example, https://x.example/doge.png}
キャッシュキー: { https://a.examplehttps://c.examplehttps://x.example/doge.png }

ユーザーは https://a.example に戻りましたが、今回は、https://c.example の iframe で画像がホストされています。

この場合、https://a.examplehttps://c.examplehttps://x.example/doge.png で構成されるキーに一致するリソースがキャッシュに存在しないため、ネットワークからイメージがダウンロードされます。

キャッシュキー { https://a.example, https://a.example, https://x.example/doge.png}
キャッシュキー: { https://a.examplehttps://c.examplehttps://x.example/doge.png }

ドメインにサブドメインやポート番号が含まれている場合はどうなりますか?ユーザーが https://subdomain.a.example にアクセスし、iframe(https://c.example:8080)が埋め込まれて画像をリクエストします。

鍵は「scheme://eTLD+1」に基づいて作成されるため、サブドメインとポート番号は無視されます。そのため、キャッシュ ヒットが発生します。

キャッシュキー { https://a.example, https://a.example, https://x.example/doge.png}
キャッシュキー: { https://a.examplehttps://c.examplehttps://x.example/doge.png }

iframe が複数回ネストされている場合、どうすればよいですか。ユーザーが https://a.example にアクセスすると、iframe(https://b.example)が埋め込まれ、さらに別の iframe(https://c.example)が埋め込まれて、最終的に画像がリクエストされます。

キーはトップフレーム(https://a.example)と、リソースを読み込む即時フレーム(https://c.example)から取得されるため、キャッシュ ヒットが発生します。

よくある質問

すでに Chrome で有効になっていますか?どうすれば確認できますか?

この機能は 2020 年後半にリリースされる予定です。使用している Chrome インスタンスがこの機能をすでにサポートしているかどうかを確認するには:

  1. chrome://net-export/ を開き、[Start Logging to Disk] を押します。
  2. ログファイルの保存場所を指定します。
  3. Chrome でウェブを 1 分間ブラウジングします。
  4. chrome://net-export/ に戻り、[Stop Logging] を押します。
  5. https://netlog-viewer.appspot.com/#importに向かいます。
  6. [Choose File] を押し、保存したログファイルを渡します。

ログファイルの出力が表示されます。

同じページで SplitCacheByNetworkIsolationKey を探します。名前の後に Experiment_[****] が続く場合、Chrome で HTTP キャッシュ パーティショニングが有効になっています。その後に Control_[****] または Default_[****] が続くと、有効にはなりません。

Chrome で HTTP キャッシュ パーティショニングをテストするにはどうすればよいですか?

Chrome で HTTP キャッシュ パーティショニングをテストするには、コマンドライン フラグ --enable-features=SplitCacheByNetworkIsolationKey を指定して Chrome を起動する必要があります。プラットフォームでコマンドライン フラグを指定して Chrome を起動する方法については、フラグを指定して Chromium を実行するをご覧ください。

今回の変更について、ウェブ デベロッパーとして何か対応すべきことはありますか?

これは互換性を損なう変更ではありませんが、一部のウェブサービスのパフォーマンスに対する考慮事項が加わる可能性があります。

たとえば、キャッシュ可能なリソースを多くのサイトで大量に提供するサイト(フォントや一般的なスクリプトなど)では、トラフィックが増加する可能性があります。また、そのようなサービスの利用者は、サービスへの依存度が高まっている可能性があります。

ウェブ共有ライブラリプレゼンテーション動画)と呼ばれるプライバシー保護の方法で共有ライブラリを有効にする提案がありますが、まだ検討中です)。

この行動の変化にはどのような影響がありますか?

全体的なキャッシュミス率は約 3.6% 増加し、FCP(First Contentful Paint)の変化はわずか(約 0.3%)で、ネットワークから読み込まれるバイト数の合計は約 4% 増加します。パフォーマンスへの影響については、HTTP キャッシュ パーティショニングの説明をご覧ください。

これは標準化されているか?他のブラウザでは異なる動作をしますか?

「HTTP キャッシュ パーティション」は取得仕様で標準化されていますが、ブラウザの動作は異なります。

  • Chrome: トップレベル スキーム://eTLD+1 とフレーム スキーム://eTLD+1 を使用
  • Safari: トップレベルの eTLD+1 を使用
  • Firefox: トップレベル スキーム://eTLD+1 を実装する予定で、2 つ目のキー(Chrome など)を含めることを検討中

ワーカーからの取得はどのように処理されますか?

専用ワーカーは、現在のフレームと同じキーを使用します。Service Worker と共有ワーカーは、複数のトップレベル サイト間で共有される可能性があるため、より複雑です。このソリューションは現在検討中です。

リソース