COOP と COEP を使用してウェブサイトを「クロスオリジン分離」にする

COOP と COEP を使用してクロスオリジン分離環境を設定し、SharedArrayBuffer、performance.measureUserAgentSpecificMemory()、高解像度タイマーなどの強力な機能をより高い精度で有効にします。

公開日: 2020 年 4 月 13 日、最終更新日: 2022 年 6 月 21 日

このドキュメントでは、これらの COOP と COEP の使用方法について説明します。これが重要である理由については、COOP と COEP を使用してウェブサイトを「クロスオリジン分離」にするをご覧ください。

一部のウェブ API は、Spectre などのサイドチャネル攻撃のリスクを高めます。このリスクを軽減するため、ブラウザにはクロスオリジン分離と呼ばれるオプトイン ベースの分離環境が用意されています。クロスオリジン分離状態では、ウェブページは次のような特権機能を使用できます。

API 説明
SharedArrayBuffer WebAssembly スレッドに必要です。これは Android 版 Chrome 88 から利用できます。PC 版は、サイト分離によりデフォルトで有効になっていますが、クロスオリジン分離状態が必要となり、Chrome 92 ではデフォルトで無効になります。
performance.measureUserAgentSpecificMemory() Chrome 89 以降で利用できます。
performance.now()、performance.timeOrigin 多くのブラウザで利用できますが、解像度は 100 マイクロ秒以上に制限されています。クロスオリジン分離を使用すると、解像度を 5 マイクロ秒以上にできます。
クロスオリジン分離状態で利用可能になる機能。

クロスオリジン分離状態では、document.domain の変更も防止されます。(document.domain を変更できると、同一サイトのドキュメント間の通信が可能になり、同一オリジン ポリシーの抜け穴と見なされていました)。

クロスオリジン分離状態を有効にするには、メイン ドキュメントで次の HTTP ヘッダーを送信する必要があります。

Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Opener-Policy: same-origin

これらのヘッダーは、クロスオリジン ドキュメントによる読み込みをオプトインしていないリソースまたは iframe の読み込みをブロックし、クロスオリジン ウィンドウがドキュメントと直接やり取りするのを防ぐようブラウザに指示します。これは、クロスオリジンで読み込まれるリソースにはオプトインが必要であることを意味します。

ウェブページがクロスオリジン分離状態にあるかどうかは、self.crossOriginIsolated を調べることで判断できます。

用語集

このドキュメントでは、類似した名前や略語が多数使用されています。わかりやすくするために、簡単な用語集を用意しました。

ウェブサイトをクロスオリジン分離にする

1. 最上位ドキュメントに Cross-Origin-Opener-Policy: same-origin を設定する

最上位ドキュメントで COOP: same-origin を有効にすると、同じオリジンのウィンドウとドキュメントから開かれたウィンドウは、同じ COOP 設定の同じオリジンにない限り、別のブラウジング コンテキスト グループを持ちます。したがって、開かれたウィンドウに対して分離が適用され、両方のウィンドウ間の相互通信が無効になります。

ブラウジング コンテキスト グループは、相互に参照できるウィンドウのセットです。たとえば、最上位ドキュメントとその子ドキュメントが <iframe> で埋め込まれている場合です。ウェブサイト(https://a.example)がダイアログ ウィンドウ(https://b.example)を開くと、オープナー ウィンドウとダイアログ ウィンドウは同じブラウジング コンテキストを共有するため、window.opener などの DOM API を使用して相互にアクセスできます。

ユーザーがページ要素を操作している、ブラウジング コンテンツ グループを表すイラスト。

ウィンドウを開いた側とそのウィンドウが別のブラウジング コンテキスト グループに属しているかどうかは、DevTools から確認できます。

2. リソースで CORP または CORS を有効にする

ページ内のすべてのリソースが CORP または CORS HTTP ヘッダーで読み込まれていることを確認します。このステップは、ステップ 4 の COEP の有効化に必要です。

リソースの性質に応じて、次の対応が必要になります。

  • リソースが同じオリジンからのみ読み込まれることが想定される場合は、Cross-Origin-Resource-Policy: same-origin ヘッダーを設定します。
  • リソースが同じサイトからのみ、ただしクロスオリジンで読み込まれることが想定される場合は、Cross-Origin-Resource-Policy: same-site ヘッダーを設定します。
  • リソースが管理下のクロスオリジンから読み込まれる場合は、可能であれば Cross-Origin-Resource-Policy: cross-origin ヘッダーを設定します。
  • 管理できないクロスオリジン リソースの場合:
    • リソースが CORS で提供される場合は、読み込み HTML タグで crossorigin 属性を使用します。(たとえば <img src="***" crossorigin>)で保護しなければなりません。
    • リソースの所有者に、CORS または CORP のいずれかをサポートするよう依頼してください。
  • iframe の場合も同じ原則に従い、Cross-Origin-Resource-Policy: cross-origin(またはコンテキストに応じて same-site、same-origin)を設定します。
  • WebWorker で読み込まれたスクリプトは同一オリジンから提供される必要があるため、CORP ヘッダーや CORS ヘッダーは必要ありません。
  • COEP: require-corp で提供されるドキュメントまたはワーカーの場合、CORS なしで読み込まれるクロスオリジン サブリソースは、Cross-Origin-Resource-Policy: cross-origin ヘッダーを設定して埋め込みを有効にする必要があります。たとえば、<script>、importScripts、<link>、<video>、<iframe> などがこれに該当します。

iframe での分離

iframe 内に埋め込まれたドキュメントでクロスオリジン分離を有効にするには、allow="cross-origin-isolated" 権限ポリシーを <iframe> タグに適用し、次の条件を満たす必要があります。親フレームと子フレームを含むドキュメントのチェーン全体も、クロスオリジン分離されている必要があります。

3. COEP Report-Only HTTP ヘッダーを使用して埋め込みリソースを評価する

COEP を完全に有効にする前に、Cross-Origin-Embedder-Policy-Report-Only ヘッダーを使用してドライランを行い、ポリシーが実際に機能するかどうかを調べることができます。埋め込みコンテンツをブロックせずにレポートを受け取ることができます。

最上位のドキュメント、iframe、ワーカー スクリプトを含むすべてのドキュメントに、この処理を再帰的に適用します。Report-Only HTTP ヘッダーの詳細については、Reporting API を使用して問題を監視するをご覧ください。

4. COEP を有効にする

このステップは、リソースで CORP または CORS が有効になっていることを確認した後にのみ実行できます。

すべてが正常に動作し、すべてのリソースを正常に読み込めることを確認したら、Cross-Origin-Embedder-Policy-Report-Only ヘッダーを、iframe やワーカー スクリプトが埋め込まれているドキュメントを含むすべてのドキュメントで同じ値を持つ Cross-Origin-Embedder-Policy ヘッダーに切り替えます。

分離が成功したかどうかを判断する

ウェブページがクロスオリジン分離状態にあり、すべてのリソースとウィンドウが同じブラウジング コンテキスト グループ内で分離されている場合、self.crossOriginIsolated プロパティは true を返します。この API を使用すると、ブラウジング コンテキスト グループを正常に分離し、performance.measureUserAgentSpecificMemory() などの機能にアクセスできるかどうかを判断できます。

問題のデバッグ

COOP と COEP で問題が発生することがあります。デバッグには、ブラウザのデベロッパー ツールまたは Reporting API を使用できます。

Chrome DevTools でデバッグする

画像など、画面にレンダリングされるリソースの場合、リクエストがブロックされ、ページに画像がないことが示されるため、COEP の問題を簡単に検出できます。ただし、スクリプトやスタイルなど、必ずしも視覚的な影響がないリソースの場合、COEP の問題が見過ごされる可能性があります。これらについては、DevTools の [ネットワーク] パネルを使用します。

COEP に問題がある場合は、[ステータス] 列に (blocked:NotSameOriginAfterDefaultedToSameOriginByCoep) が表示されます。

ネットワーク パネルの [ステータス] 列に表示される COEP の問題。

エントリをクリックすると、詳細が表示されます。

COEP の問題の詳細は、[ネットワーク] パネルでネットワーク リソースをクリックすると、[ヘッダー] タブに表示されます。

[Application] パネルで、iframe とダイアログ ウィンドウのステータスを確認することもできます。左側の [Frames] セクションに移動し、[top] を展開してリソース構造の内訳を確認します。

SharedArrayBuffer の可用性など、iframe のステータスを確認できます。

Chrome DevTools の iframe インスペクタ。

クロスオリジン分離されているかどうかなど、ダイアログ ウィンドウのステータスを確認することもできます。

Chrome DevTools ダイアログ ウィンドウ インスペクタ

Reporting API を使用して問題をモニタリングする

Reporting API は、さまざまな問題を検出できるもう 1 つのメカニズムです。Reporting API を構成して、COEP がリソースの読み込みをブロックしたり、COOP がダイアログ ウィンドウを分離したりするたびに、ユーザーのブラウザにレポートを送信するように指示できます。Chrome は、COEP や COOP などのさまざまな用途で、バージョン 69 以降 Reporting API をサポートしています。

Reporting API を構成し、レポートを受信するようにサーバーを設定する方法を学習する。

COEP レポートの例

クロスオリジン リソースがブロックされた場合の COEP レポート ペイロードの例を次に示します。

[{
  "age": 25101,
  "body": {
    "blocked-url": "https://third-party-test.example.org/check.svg?",
    "blockedURL": "https://third-party-test.example.org/check.svg?",
    "destination": "image",
    "disposition": "enforce",
    "type": "corp"
  },
  "type": "coep",
  "url": "https://cross-origin-isolation.example.com/?coep=require-corp&coop=same-origin&",
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4249.0 Safari/537.36"
}]

COOP レポートの例

ダイアログが分離されて開かれた場合の COOP レポートのペイロードの例を次に示します。

[{
  "age": 7,
  "body": {
    "disposition": "enforce",
    "effectivePolicy": "same-origin",
    "nextResponseURL": "https://third-party-test.example.org/popup?report-only&coop=same-origin&",
    "type": "navigation-from-response"
  },
  "type": "coop",
  "url": "https://cross-origin-isolation.example.com/coop?coop=same-origin&",
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4246.0 Safari/537.36"
}]

異なるブラウジング コンテキスト グループが互いにアクセスしようとした場合(「レポートのみ」モードの場合のみ)、COOP はレポートを送信します。たとえば、postMessage() が試行された場合のレポートは次のようになります。

[{
  "age": 51785,
  "body": {
    "columnNumber": 18,
    "disposition": "reporting",
    "effectivePolicy": "same-origin",
    "lineNumber": 83,
    "property": "postMessage",
    "sourceFile": "https://cross-origin-isolation.example.com/popup.js",
    "type": "access-from-coop-page-to-openee"
  },
  "type": "coop",
  "url": "https://cross-origin-isolation.example.com/coop?report-only&coop=same-origin&",
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4246.0 Safari/537.36"
},
{
  "age": 51785,
  "body": {
    "disposition": "reporting",
    "effectivePolicy": "same-origin",
    "property": "postMessage",
    "type": "access-to-coop-page-from-openee"
  },
  "type": "coop",
  "url": "https://cross-origin-isolation.example.com/coop?report-only&coop=same-origin&",
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4246.0 Safari/537.36"
}]

要点

COOP と COEP の HTTP ヘッダーを組み合わせて使用すると、ウェブページを特別なクロスオリジン分離状態にできます。self.crossOriginIsolated を調べると、ウェブページがクロスオリジン分離状態かどうかを判断できます。

このクロスオリジン分離状態に新しい機能が追加され、COOP と COEP に関する DevTools のさらなる改善が行われるたびに、この投稿を更新していきます。

リソース

ドキュメントの更新

  • 2022 年 6 月 21 日: クロスオリジン分離が有効になっている場合は、ワーカー スクリプトにも注意が必要です。説明を追加しました。
  • 2021 年 8 月 5 日: JS Self-Profiling API は、クロスオリジン分離を必要とする API の 1 つとして言及されていましたが、最近の方向性の変更を反映して削除されました。
  • 2021 年 5 月 6 日: 寄せられたフィードバックと報告された問題に基づき、クロスオリジン分離されていないサイトでの SharedArrayBuffer の使用を Chrome M92 で制限するよう、タイムラインを調整することにしました。
  • 2021 年 4 月 16 日: COEP 認証情報なしモードと、クロスオリジン分離の緩和条件となる COOP same-origin-allow-popups に関するメモを追加しました。
  • 2021 年 3 月 5 日: SharedArrayBuffer、performance.measureUserAgentSpecificMemory()、デバッグ機能の制限を削除しました。これらの機能は Chrome 89 で完全に有効になりました。より精度の高い、今後の機能 performance.now() と performance.timeOrigin を追加しました。
  • 2021 年 2 月 19 日: DevTools の機能ポリシーallow="cross-origin-isolated"とデバッグ機能に関するメモを追加しました。
  • 2020 年 10 月 15 日: self.crossOriginIsolated は Chrome 87 から利用できます。これを反映して、self.crossOriginIsolated が true を返す場合、document.domain は不変です。performance.measureUserAgentSpecificMemory() はオリジン トライアルを終了し、Chrome 89 でデフォルトで有効になります。Android Chrome の Shared Array Buffer は Chrome 88 から利用可能になります