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://parent.example.comhttps://video.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 の [問題] パネルに警告が表示されます。この警告は 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.compostMessage() でメッセージを送信して、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 で a document.domain タグを使用して質問してください。postMessage()

最後の手段として、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 を送信する必要があります(1 つのドキュメントのみが設定しても document.domain は無効になります)。

エンタープライズ ポリシーの OriginAgentClusterDefaultEnabled を構成する

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

リソース

謝辞

撮影者: Finan AkbarUnsplash