Chrome で document.domain の変更が無効化される

ウェブサイトが document.domain の設定に依存している場合は、対応が必要です。

変更点とその理由

Chrome 115 以降、ウェブサイトは document.domain を設定できなくなります。Chrome では document.domain を変更不可にします。クロスオリジン通信を行うには、postMessage() や Channel Messaging API などの代替方法を使用する必要があります。

この変更は段階的にロールアウトされます。

他のブラウザでも、この機能は最終的に非推奨になり、削除される予定です。詳しくは、ブラウザの互換性のセクションをご覧ください。

document.domain を不変にする理由

document.domain は、送信元のホスト名を取得または設定するように設計されています。多くのウェブサイトでは、同一サイトのクロスオリジンページ間の通信を許可するために document.domain を設定しています。

これは便利な手法ですが、同一生成元ポリシーを緩和するため、セキュリティ リスクが生じます。document.domain に関するセキュリティ上の懸念から、仕様が変更され、使用しないようユーザーに警告しています。

詳細: document.domain を不変にする理由

document.domain の現在の使用方法

多くのウェブサイトでは、同一サイトのクロスオリジンページ間の通信を許可するために document.domain を設定しています。

同じサイトでもクロスオリジンのサイトは、eTLD+1 は同じですが、サブドメインが異なります。

これまでの document.domain の使用方法は次のとおりです。

https://parent.example.com のページに https://video.example.com の iframe ページが埋め込まれているとします。これらのページは、同じ eTLD+1(example.com)で、サブドメインが異なります。両方のページの document.domain'example.com' に設定されている場合、ブラウザは 2 つのオリジンを同じオリジンとして扱います。

https://parent.example.comdocument.domain を設定します。

// Confirm the current origin of "parent.example.com"
console.log(document.domain);

// Set the document.domain
document.domain = 'example.com';
console.log(document.domain);

https://video.example.comdocument.domain を設定します。

// Confirm the current origin of "video.example.com"
console.log(document.domain);

// Set the document.domain
document.domain = 'example.com';
console.log(document.domain);

https://video.example.com に対して https://parent.example.com でクロスオリジン DOM 操作を作成できるようになりました。

ウェブサイトは、同じサイトのドキュメントがより簡単に通信できるように document.domain を設定します。この変更により同一オリジン ポリシーが緩和されるため、親ページは iframe のドキュメントにアクセスして DOM ツリーを走査できるようになります。その逆も同様です。

これは便利な手法ですが、セキュリティ上のリスクがあります。

document.domain のセキュリティに関する懸念

document.domain に関するセキュリティ上の懸念から、その使用を避けるようユーザーに警告する仕様が変更されました。

たとえば、2 つのページが document.domain を設定すると、同じオリジンであるかのように見せかけることができます。これは、これらのページが異なるサブドメインを持つ共有ホスティング サービスを使用する場合に特に重要です。document.domain を設定すると、同じサービスでホストされている他のすべてのサイトにアクセスできるようになります。これにより、攻撃者がサイトに簡単にアクセスできるようになります。これは、document.domain がドメインのポート番号部分を無視するためです。

document.domain の設定によるセキュリティ上の影響の詳細については、MDN の「Document.domain」ページをご覧ください。

ブラウザの互換性

サイトが影響を受けているかどうかを確認するにはどうすればよいですか?

ウェブサイトがこの変更の影響を受ける場合は、Chrome の DevTools の [Issues] パネルに警告が表示されます。この警告は 2022 年に追加されました。DevTools の右上に黄色のフラグが表示されます。

DevTools の問題警告のスクリーンショット

LightHouse の非推奨 API 監査でサイトを実行して、Chrome から削除される予定のすべての API を確認することもできます。

Reporting API を設定している場合は、このサポート終了について通知する非推奨レポートが Chrome から送信されています。既存のレポート収集サービスを使用するか、独自の社内ソリューションを構築して Reporting API を使用する方法について学びます。

この変更の実装例を確認するにはどうすればよいですか?

この変更は、Chrome 115 以降、段階的に展開されます。Chrome ブラウザにまだロールアウトされていない場合でも、この変更を有効にするには、次の手順を行います。

  1. chrome://flags/#origin-agent-cluster-default を開きます。
  2. [有効にする] を選択します。
  3. Chrome を再起動します。

代替手段はありますか?

最善の方法は、ページとすべての構成フレームを同じオリジンでホストするなど、document.domain をまったく変更しないことです。これは、すべてのブラウザのすべてのバージョンで機能します。ただし、これを行うにはアプリを大幅に変更する必要があるため、引き続きクロスオリジン アクセスをサポートする代替手段も検討することをおすすめします。

document.domain の代わりに postMessage() または Channel Messaging API を使用する

ほとんどのユースケースでは、クロスオリジン postMessage() または Channel Messaging APIdocument.domain を置き換えることができます。

下記の例で、

  1. https://parent.example.com は iframe 内の https://video.example.com をリクエストし、postMessage() を介してメッセージを送信して DOM を操作します。
  2. https://video.example.com は、メッセージを受信するとすぐに DOM を操作し、成功を親に通知します。
  3. https://parent.example.com は成功を通知します。

https://parent.example.com:

// Send a message to https://video.example.com
iframe.postMessage('Request DOM manipulation', 'https://video.example.com');

// Receive messages
iframe.addEventListener('message', (event) => {
  // Reject all messages except ones from https://video.example.com
  if (event.origin !== 'https://video.example.com') return;

  // Filter success messages
  if (event.data === 'succeeded') {
    // DOM manipulation is succeeded
  }
});

https://video.example.com:

// Receive messages
window.addEventListener('message', (event) => {
  // Reject all messages except ones from https://parent.example.com
  if (event.origin !== 'https://parent.example.com') return;

  // Do a DOM manipulation on https://video.example.com.

  // Send a success message to https://parent.example.com
  event.source.postMessage('succeeded', event.origin);
});

ぜひお試しください。postMessage() または Channel Messaging API では対応できない特定の要件がある場合は、Twitter の @ChromiumDev でお問い合わせいただくか、Stack Overflow で document.domain タグを使用してお問い合わせください。

最後の手段として、Origin-Agent-Cluster: ?0 ヘッダーを送信する

document.domain の設定を継続する正当な理由がある場合は、ターゲット ドキュメントとともに Origin-Agent-Cluster: ?0 レスポンス ヘッダーを送信できます。

Origin-Agent-Cluster: ?0

Origin-Agent-Cluster ヘッダーは、ドキュメントをオリジンキー エージェント クラスタで処理するかどうかをブラウザに指示します。Origin-Agent-Cluster の詳細については、Origin-Agent-Cluster ヘッダーを使用してパフォーマンス分離をリクエストするをご覧ください。

このヘッダーを送信すると、ドキュメントはデフォルトで変更不可になっても document.domain を設定し続けることができます。

この動作を必要とする他のすべてのドキュメントも Origin-Agent-Cluster を送信する必要があります(document.domain を 1 つのドキュメントでのみ設定している場合、効果はありません)。

企業向けポリシーの OriginAgentClusterDefaultEnabled を構成する

必要に応じて、管理者は OriginAgentClusterDefaultEnabled ポリシーを false に構成して、組織全体の Chrome インスタンスで document.domain をデフォルトで設定できるようにします。詳しくは、Chrome Enterprise のポリシーリストと管理 | ドキュメントをご覧ください。

リソース

謝辞

写真提供: Finan AkbarUnsplash