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

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

Maud Nalpas 氏
Maud Nalpas
Eiji Kitamura
Eiji Kitamura

変更の内容とその理由

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 を使用します

ほとんどの場合、document.domain の代わりにクロスオリジンの postMessage() または Channel Messaging API を使用できます。

下記の例で、

  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 を送信する必要があります(1 つのドキュメントでしか設定していない場合、document.domain の効果はありません)。

エンタープライズ ポリシー向けに OriginAgentClusterDefaultEnabled を設定する

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

関連情報

謝辞

写真撮影: Finan AkbarUnsplash