跨 Realm 的浏览器一致性与隐私边界
在 Window、Worker 和 iframe 之间保持明确的数据契约,不把 JavaScript 对象差异误当成身份信号。
BotBrowser Team
应用可以保持 Window、Worker 与 iframe 之间的边界可预测,并在这些上下文交换消息时限制数据暴露。WHATWG HTML 规范定义了这些 Realm,BotBrowser 可以在受控上下文中重复授权流程并比较可见结果,但不能保证远程网站的隐私行为。
一个页面可以包含多个 Realm
WHATWG HTML 规范定义了这些边界;BotBrowser 可以在声明的受控上下文中重复授权流程,但本地检查不等于远程隐私保证。
顶层 Window 不是唯一的 JavaScript 环境。专用 Worker 有自己的全局作用域,iframe 也会创建独立文档 Realm。每个 Realm 都有自己的全局对象、内置对象身份、事件调度参与方式、存储规则和策略上下文。因此,Array 或 Object 这类引用必须按创建它的 Realm 来理解。
这些边界上的一致性与隐私并不要求所有 Realm 暴露完全相同的对象或时序。可执行的合同是:应用知道值由哪个 Realm 所有,通过明确边界交换数据,并且不把正常差异变成持久标识符。
哪些内容会跨越边界
同源 frame 可以通过 Window.postMessage 通信,Worker 也可以和拥有它的页面通过 postMessage 通信。结构化克隆会复制许多值,而不是共享原对象。接收 Realm 中创建的数组不是发送方数组的同一个对象,即使内容相同。ArrayBuffer 等可转移对象则可以转移所有权;转移后发送方必须把原缓冲区视为已分离。
跨源 frame 仍受同源策略隔离。虽然可以使用 postMessage,接收方仍须校验 event.origin,必要时还要校验发送方标识或 nonce。event.source 是 WindowProxy 引用,不是可信凭证。不要用消息形状、构造函数身份或浏览器特定异常来完成认证。
Worker 没有文档 DOM。它可以接收数据、计算并返回结果,但不能直接读取页面元素,也不能假定页面的存储和权限状态。Service Worker 还有不同的生命周期和作用域,不应与专用 Worker 或 iframe 混用。
一致性需要显式合同
为 Window 到 Worker 或 iframe 的每个值定义 schema、所有权和生命周期。优先发送接收方能校验的普通记录、数组、字符串和数字;消息可能跨版本时加入版本字段。不要发送函数、DOM 节点或 Realm 专属原型并期待行为保留。需要转移时,记录交付后哪个一方拥有资源。
下面的最小 fixture 只使用合成数据:
const worker = new Worker('/realm-worker.js', { type: 'module' });
const request = { version: 1, values: [2, 3, 5] };
worker.onmessage = ({ data }) => {
if (data?.version !== 1 || !Array.isArray(data.values)) throw new Error('invalid reply');
console.log({ sum: data.values.reduce((a, b) => a + b, 0), realm: data.realm });
};
worker.postMessage(request);
// realm-worker.js
self.onmessage = ({ data }) => {
if (data?.version !== 1 || !Array.isArray(data.values)) return;
self.postMessage({ version: 1, values: data.values, realm: 'worker' });
};
realm 是应用数据,不是浏览器指纹。它只帮助测试确认预期路径,不应作为用户身份属性持久化。
应保留的隐私边界
iframe 只能观察自己的文档和权限所暴露的内容。同源 iframe 可能拥有更宽的应用访问权,跨源 iframe 则应只收到明确委派的消息和能力。使用窄化的 postMessage 协议、精确的 targetOrigin,并在需要时声明 sandbox 或 Permissions Policy。不要因为通道可用就传递账户记录、令牌或无关的浏览器观察值。
Worker 可以减少对 DOM 的暴露,但把代码移入 Worker 不会让输入对提供输入的页面或接收输入的服务自动私密。Worker 也能观察其全局作用域可用的 API。数据最小化、保留和同意属于应用政策,不是选用 Worker 的自动结果。
Realm 差异可能可测量:构造函数身份、功能可用性、语言设置和调度观察都可能不同。单个观察不能证明浏览器品牌、设备或个人。不要把多个 Realm 探测组合成隐蔽的跨上下文标识符,只测试应用所需能力,并在审查结束后删除诊断输出。
决策表
| 观察 | 所属方 | 安全动作 | 不应推断 |
|---|---|---|---|
| 消息 schema 校验失败 | 接收 Realm | 拒绝并报告合成错误 | 发送方身份或恶意意图 |
event.origin 不符合预期 | 接收方策略 | 忽略并记录有限事件 | 该源的所有消息都可信 |
| 值被克隆 | 结构化克隆 | 校验内容并使用接收方对象 | 共享原型或对象身份 |
| 可转移对象已分离 | 转移合同 | 停止使用发送方资源 | 浏览器故障或用户身份 |
| Worker/iframe 缺少功能 | Realm 能力 | 使用文档化回退 | 独特设备或浏览器 |
BotBrowser 能力与限制
BotBrowser 支持在受控上下文中重复授权的 Window、Worker 和 iframe 流程,但不能让各 Realm 一致,也不能证明远程网站的隐私行为。
BotBrowser 受控上下文可以在声明的配置中重复运行授权的 Window、Worker 和 iframe 流程,并比较隔离上下文中的可见消息结果。这适合检查应用自己的 Realm 协议、源校验和回退行为。BotBrowser 不会让各 Realm 完全相同,不会授予跨源访问,也不认证消息,不保证每个浏览器版本具有相同的 Worker 或 iframe 功能。它不能控制远程网站保留什么;本地一致性检查也不是匿名或生产隐私的证明。
导航测试应只保留诊断合同所需的可见状态。
预期结果应同时描述成功路径和能力缺失时的恢复动作。
新上下文有助于发现继承状态,但不能证明远程服务器删除了数据。
即使校验失败,应用也应关闭 Worker、frame 和临时服务器。
请求标识符可以限制重试次数,并把响应关联到正确的操作。
界面应使用可访问文本报告超时,并提供清晰的恢复选择。
合成数据让测试可重复,也减少真实内容的暴露。
iframe 导航后如果来源改变,接受响应前必须重新检查协议。
权限策略应说明每个 frame 获得哪些能力,以及授予它们的原因。
隐私审查应覆盖两个 Realm 中数据的生命周期和错误路径。
Realm 之间的差异是兼容性信号,不是用户身份。
公开来源
- WHATWG HTML:Web application APIs and realms
- WHATWG HTML:Web messaging
- MDN:Using web workers
- MDN:Window.postMessage
- BotBrowser advanced features