Chrome 将禁止修改 document.domain 以放宽同源政策

如果您的网站依赖于设置 document.domain,则需要采取必要的措施。

Eiji Kitamura
北村英二

更新

  • 2023 年 5 月 30 日:我们已宣布将于 Chrome 115 中弃用 document.domain setter。
  • 2023 年 4 月 7 日:我们在 Chrome 112 中发布此变更之前,发现了一个问题。默认移除的 document.domain setter 目前已暂停,并且尚未确定新的发布里程碑。请不时回来看看本博文,或者订阅 blink-dev此会话
  • 2023 年 1 月 20 日:更新了时间轴 - 从 Chrome 112 开始,document.domain setter 将默认移除。此外,还添加了关于企业政策的内容,用于控制 document.domain 行为。
  • 2022 年 7 月 25 日:更新了时间轴 - 从 Chrome 109 开始,document.domain setter 将默认移除。
  • 2022 年 2 月 4 日:更新了新的时间表 - 从 Chrome 100 开始,“问题”面板中将显示警告,从 Chrome 106 开始,系统会默认移除 document.domain setter。

document.domain 旨在获取或设置源站的主机名。

在 Chrome 中,网站无法设置 document.domain。您将需要使用 postMessage() 或 Channel Messaging API 等其他方法进行跨源通信。我们的目标是让 Chrome 112 尽早发布此变更,但这取决于对 Intent to Ship 的响应。

如果您的网站依赖于通过 document.domain 放宽同源政策才能正常运行,那么该网站将需要发送 Origin-Agent-Cluster: ?0 标头,需要该行为的所有其他文档也是如此(请注意,如果只有一个文档设置了 document.domain 标头,则不会产生任何影响)。

为什么要使 document.domain 不可变?

许多网站将 document.domain 设置为允许在同一网站但跨源网页之间进行通信。

其使用方法如下:

假设 https://parent.example.com 上的某个页面嵌入了 https://video.example.com 中的 iframe 页面。这些网页具有相同的 eTLD+1 (example.com),但存在不同的子网域。如果两个网页的 document.domain 均设置为 'example.com',浏览器会将这两个来源视为同一来源。

https://parent.example.com 设置 document.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.com 设置 document.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.com 上针对 https://video.example.com 创建跨源 DOM 操作。

网站设置 document.domain 是为了便于同网站文档的通信更轻松。由于这项更改放宽了同源政策,因此父页面能够访问 iframe 的文档并遍历 DOM 树,反之亦然。

这是一种便捷的方法,但会带来安全风险。

document.domain 的安全问题

围绕 document.domain 的安全问题导致警告用户应避免使用的规范发生变化。当前与其他浏览器供应商的讨论正在朝着同一方向发展。

例如,当两个页面设置 document.domain 时,它们可以假装它们是同源。当这些网页使用包含不同子网域的共享托管服务时,这一点尤为重要。设置 document.domain 后,用户就可以访问由同一服务托管的所有其他网站,让攻击者可以更轻松地访问您的网站。之所以能够这么做,是因为 document.domain 会忽略网域的端口号部分。

如需详细了解设置 document.domain 的安全隐患,请参阅 MDN 上的“Document.domain”页面

Chrome 计划在 Chrome 112 中使 document.domain 不可变。

如何知道自己的网站是否受到影响?

如果您的网站受此变更的影响,Chrome 将在开发者工具的“问题”面板中发出警告。请注意右上角的黄色旗帜。

修改 document.domain 后,“Problem”面板中会显示一条警告。
修改 document.domain 后,“问题”面板中会显示一条警告。

如果您设置了报告端点,还会收到弃用报告。详细了解如何将 Reporting API 与现有报告收集服务搭配使用,或构建您自己的内部解决方案。

您可以通过 LightHouse 已弃用 API 审核运行您的网站,找出所有计划从 Chrome 中移除的 API。

替代跨源通信

目前,您可以通过以下三种方式为网站替换 document.domain

使用 postMessage() 或 Channel Messaging API

在大多数用例中,跨源 postMessage()Channel Messaging API 可以替换 document.domain

在以下示例中:

  1. https://parent.example.com 通过 postMessage() 发送消息,在 iframe 中请求 https://video.example.com 来操控 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 的特定要求,请通过 @ChromiumDev 在 Twitter 上告诉我们,或者在 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,即使它默认变得不可变也是如此。

为企业政策配置“OriginAgentClusterDefaultEnabled

或者,您的管理员可以将 OriginAgentClusterDefaultEnabled 政策配置为 false,从而在组织中的 Chrome 实例上默认将 document.domain 设置为可设置。有关详情,请参阅 Chrome 企业版政策列表和管理 | 文档

浏览器兼容性

资源

致谢

照片由 Braydon Anderson 拍摄,选自 Unsplash 用户