为了加强用户隐私保护并打击边信道跨网站跟踪,Chrome 现在通过一种称为“存储空间分区”的流程,在第三方上下文中隔离了大多数存储空间和通信 API。
实现状态
此功能已面向 Chrome 115 及更高版本的所有用户启用。其他主要浏览器(如 Firefox 和 Safari)也已实施或计划实施类似的存储空间分区措施。GitHub 上的存储空间分区提案正在公开征求进一步的讨论。
什么是存储分区?
为防止某些类型的边信道跨网站跟踪,Chrome 会将存储空间和通信 API 划分到第三方上下文中。
如果不进行存储分区,网站可以联接不同网站的数据,以跟踪用户在整个网络中的活动。此外,嵌入式网站还可以使用侧信道技术(例如时序攻击、XS-Leaks 和 COSI)推断顶级网站中用户的特定状态。
过去,存储空间仅按来源进行键控。这意味着,如果 example.com 的 iframe 嵌入到 a.com 和 b.com 中,它可以通过存储和成功检索存储空间中的 ID 来了解您在这两个网站上的浏览习惯。启用第三方存储分区后,example.com 的存储空间位于两个不同的分区中,一个用于 a.com,另一个用于 b.com。
一般来说,分区是指 iframe 内通过 Local Storage 和 IndexedDB 等存储 API 写入的数据不再能被共享同一来源的所有上下文访问。现在,该数据已被隔离,仅供具有相同来源和相同顶级网站的上下文使用。
链式 iframe 中的存储分区
当 iframe 嵌套时,存储分区会变得非常复杂,尤其是在链中多次出现同一来源时。
例如,A1 包含 B 的 iframe,而 B 包含 A2 的 iframe,并且 A1 和 A2 位于同一网站上。如果分区仅考虑顶级网站和当前框架的来源,则 iframe A2 可能会被错误地视为“第一方”,因为它与顶级网站 (A1) 共享一个网站,尽管两者之间存在跨网站 iframe B。如果 A2 默认有权访问未分区的存储空间,则可能会面临点击劫持等安全风险。
为了解决这个问题,Chrome 会向存储分区键添加一个“祖先位”。如果当前 iframe 与顶级网站之间的任何文档来自不同的(跨网站)来源,则会设置此位。在这种情况下,网站 B 是跨网站的,因此会为 A2 设置相应位,并且其存储空间会与 A1 分区。
当 iframe 链仅由同网站上下文组成时(例如,网站 A1 包含 A2,而 A2 又包含 A3),祖先位不会进一步划分它们的存储空间。在这种情况下,它们的存储空间仍保持共享状态,并以它们的共同来源和顶级网站为键。
对于需要在链式 iframe 之间进行未分区访问的网站,Chrome 正在尝试扩展 Storage Access API 以实现此使用情形。由于 Storage Access API 要求框架网站明确调用该 API,因此可以降低点击劫持风险。
因分区而导致的 API 变更
受分区影响的 API 可分为以下几组:
Storage API
- Web Storage API
- Web Storage API 提供了一种机制,使浏览器可以存储键值对。有两种机制:本地存储和会话存储。它们不受配额管理,但仍会进行分区。
- 源私有文件系统
- 借助 File System Access API,网站可以在用户授予访问权限后直接读取或保存对设备上文件和文件夹的更改。源私有文件系统使来源能够将私有内容直接存储到磁盘。此内容仍可供用户访问,但现在已分区。
- Storage Bucket API
- 我们正在为 Storage Standard 开发 Storage Bucket API,该 API 通过使用称为“存储分区”的新概念来整合各种存储 API,例如 IndexedDB 和 localStorage。存储分区中存储的数据以及与存储分区关联的元数据会进行分区。
- Clear-Site-Data 标头
- 在响应中包含
Clear-Site-Data标头可让服务器请求清除存储在用户浏览器中的数据。可以清除缓存、Cookie 和 DOM 存储空间。使用标头只会清除一个分区内的存储空间。
- Blob 网址存储
- Blob 网址可用于访问 blob(一种包含原始数据的对象)。如果没有存储空间分区,在一个网站上的第三方 iframe 中生成的 Blob 网址可以在嵌入到另一个网站中的同源 iframe 中使用。例如,如果
example.comiframe 同时嵌入在a.com和b.com上,则在嵌入到a.com上的 iframe 中生成的 blob 网址可以传递给嵌入到b.com上的 iframe 并由其使用,而没有任何限制。从 Chrome 137(于 2025 年 5 月 27 日发布)开始,Blob 网址将针对除顶级导航之外的所有用途进行分区。现在会遭到屏蔽的情况包括:将跨分区 Blob 网址与fetch()搭配使用,或将跨分区 Blob 网址用作各种 HTML 元素的src属性值。如果顶级导航(例如调用window.open()或点击带有target='_blank'的链接)指向 Blob 网址,且属于跨分区,则不会被屏蔽;但如果 Blob 网址网站与发起导航的网页的顶级网站属于不同的网站,则会强制执行noopener。 如果强制执行noopener,则发起导航的文档将无法获取其打开的 Blob 网址文档的窗口句柄。在前面的示例中,分区将阻止b.com上的 iframe 提取 Blob 网址的内容,但它仍然能够window.open()该网址。
通信 API
除了存储 API 之外,允许一个上下文跨来源边界进行通信的通信 API 也被分区。这些更改主要影响允许使用广播或同源 rendezvous 发现其他上下文的 API。
由于分区,以下通信 API 会阻止第三方 iframe 与其同源上下文交换数据:
- SharedWorker
- SharedWorker API 提供了一个可在相同来源的多个浏览上下文之间访问的工作器。
- Web Locks
- 借助 Web Locks API,在执行某些工作时,同一来源的一个标签页或工作器中运行的代码可以获取共享资源的锁。
Service Worker API
借助 Service Worker API,网站可以在后台执行任务。网站注册的服务工作线程会创建新的工作线程上下文来响应事件。传统上,这些 worker 可以与任何同源上下文通信。不过,由于 Service Worker 可以改变导航请求的时序,因此存在跨站信息泄露(例如历史记录嗅探)的风险。
因此,从第三方上下文注册的服务工作线程现在会进行分区。
扩展 API
扩展程序是一种可让用户自定义浏览体验的程序。
扩展程序网页(采用 chrome-extension:// 方案的网页)可以嵌入到网络上的网站中。在此场景中,扩展程序页面将继续有权访问其顶级分区。扩展程序还可以嵌入其他网站;如果扩展程序具有这些网站的主机权限,则嵌入的网站将访问其顶级分区。
如需了解详情,请参阅扩展程序文档。
演示:测试存储分区
演示网站:https://storage-partitioning-demo-site-a.glitch.me/
此演示使用两个网站:网站 A 和网站 B。
- 当您在顶级上下文中访问网站 A 时,该网站会使用各种存储方法设置数据。
- 网站 B 嵌入了网站 A 中的一个网页,并且该嵌入尝试读取之前设置的存储选项。
- 当网站 A 嵌入到网站 B 中时,如果存储空间已分区,网站 A 将无法访问该数据,因此读取操作会失败。
- 此演示使用每次读取的成功或失败来显示数据是否已分区。
目前,您可以使用 --disable-features=ThirdPartyStoragePartitioning 命令行开关在 Chrome 中关闭存储空间分区。注意:此命令行开关仅用于开发和测试目的,可能会在未来的 Chrome 版本中移除或更改。
您还可以通过相同的方式测试其他浏览器,以查看其分区状态。
申请延长迁移时间
对于需要更多时间来迁移其依赖项的网站,DisableThirdPartyStoragePartitioning3 弃用试用已延长。此试验提供了一种临时机制,让顶级网站能够选择在网页上嵌入的第三方上下文中启用未分区的存储空间、Service Worker 和通信 API。
如需了解详情,请访问存储空间分区弃用试用期续订。
互动并分享反馈
- GitHub:阅读原始提案,提出问题并参与讨论。
- 提交 bug:如果您认为某些内容未按预期运行,请在 Chromium 跟踪器中提交 bug。