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

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

更新

  • 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 日: 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 の Shared Array Buffer は 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 Report-Only HTTP ヘッダーを使用して埋め込みリソースを評価する

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

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

4. COEP を有効にする

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

self.crossOriginIsolated を使用して分離が成功したかどうかを判断する

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

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

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

[Network] パネルの [Status] 列に COEP の問題が表示されます。

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

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

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

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

Chrome DevTools の iframe インスペクタ

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

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

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

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

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 の改善がさらに進んだりするたびに更新されます。

リソース