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

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

更新

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

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

API 説明
SharedArrayBuffer WebAssembly スレッドに必要です。この機能は Android 版 Chrome 88 以降で利用できます。パソコン版は現在、サイト分離によってデフォルトで有効になっていますが、クロスオリジン分離状態が必要であり、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 を調べることで判断できます。

この記事では、これらの新しいヘッダーの使用方法について説明します。フォローアップ記事では、背景とコンテキストについて詳しく説明します。

COOP と COEP をデプロイして、ウェブサイトをクロスオリジン分離にする

COOP と COEP を統合する

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-sitesame-origin)を設定します。
  • WebWorker で読み込まれるスクリプトは同じオリジンから提供される必要があるため、CORP ヘッダーや CORS ヘッダーは必要ありません。
  • COEP: require-corp で提供されるドキュメントまたはワーカーの場合、CORS なしで読み込まれるクロスオリジン サブリソースは、埋め込みを有効にするために Cross-Origin-Resource-Policy: cross-origin ヘッダーを設定する必要があります。たとえば、<script>importScripts<link><video><iframe> などが該当します。

3. COEP のレポート専用 HTTP ヘッダーを使用して埋め込みリソースを評価する

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

最上位ドキュメント、iframe、ワーカー スクリプトを含むすべてのドキュメントにこれを再帰的に適用します。レポート専用の HTTP ヘッダーについては、Reporting API を使用して問題を確認するをご覧ください。

4. COEP を有効にする

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

self.crossOriginIsolated で分離が成功したかどうかを確認する

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

Chrome DevTools を使用して問題をデバッグする

画像など、画面にレンダリングされるリソースの場合、リクエストがブロックされ、ページに画像がないことが示されるため、COEP の問題を検出するのは比較的簡単です。ただし、必ずしも視覚的な影響を必要としないリソース(スクリプトやスタイルなど)では、COEP の問題が気づかれないことがあります。このような場合は、DevTools の [Network] パネルを使用します。COEP に問題がある場合は、[ステータス] 列に (blocked:NotSameOriginAfterDefaultedToSameOriginByCoep) と表示されます。

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

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

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

iframe とポップアップ ウィンドウのステータスは、[アプリケーション] パネルで確認することもできます。左側の [フレーム] セクションに移動し、[上] を開いてリソース構造の詳細を確認します。

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

Chrome DevTools の iframe インスペクタ

ポップアップ ウィンドウのステータス(クロスオリジン分離かどうかなど)を確認することもできます。

Chrome DevTools ポップアップ ウィンドウ インスペクタ

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

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

Reporting API を構成してレポートを受信するサーバーを設定する方法については、Reporting API の使用をご覧ください。

COEP レポートの例

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

[{
  "age": 25101,
  "body": {
    "blocked-url": "https://third-party-test.glitch.me/check.svg?",
    "blockedURL": "https://third-party-test.glitch.me/check.svg?",
    "destination": "image",
    "disposition": "enforce",
    "type": "corp"
  },
  "type": "coep",
  "url": "https://cross-origin-isolation.glitch.me/?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.glitch.me/popup?report-only&coop=same-origin&",
    "type": "navigation-from-response"
  },
  "type": "coop",
  "url": "https://cross-origin-isolation.glitch.me/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.glitch.me/popup.js",
    "type": "access-from-coop-page-to-openee"
  },
  "type": "coop",
  "url": "https://cross-origin-isolation.glitch.me/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.glitch.me/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 のさらなる改善が行われると、この投稿が更新されます。

リソース