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 の使用状況

多くのウェブサイトでは、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 に関するセキュリティ上の懸念から、ユーザーに 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 で 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