JavaScriptWeb APISecurity
ShadowRealm - JavaScript 代码隔离的新方案
收录于 2026/5/27 23:39:53
JavaScript 的 Realm 概念
单线程的准确说法:
- ❌ "JavaScript 是单线程语言"
- ✅ "一个 JavaScript realm 是单线程的"
什么是 Realm?
- 浏览器标签页 = 一个 realm(主线程)
- Web Worker = 一个 realm(worker 线程)
- 跨域
<iframe>= 独立 realm(自己的主线程)
关键特性:
- 每个 realm 有自己的全局对象(
Window、globalThis) - 每个 realm 有自己的内置对象(
Array、Object等) - 不同 realm 的全局对象不共享、不干扰
// 外部页面和 iframe 是两个独立的 realm window.globalThis === iframe.contentWindow.globalThis // Result: false window.Array === iframe.contentWindow.Array // Result: false
全局作用域污染问题
历史遗留问题:
- 函数声明会污染全局对象
- 第三方库、polyfill、广告、分析脚本都在污染全局环境
- 潜在冲突:框架 A 改了
Array.prototype,库 B 崩了
理想方案:
- 一个"干净房间"执行隔离代码
- 不影响主 realm,也不受主 realm 影响
- 但不能用 Web Worker — 因为跨线程通信受限,无法在主线程上执行
ShadowRealm API
核心设计:
- 新的 realm 类型,专门用于隔离
- 没有自己的执行线程 — 代码仍在主线程执行
- 有自己的全局对象和内置对象
- 与主 realm 完全隔离
API 只有 2 个方法:
1. evaluate() — 执行字符串代码
const shadow = new ShadowRealm(); // 主 realm 有全局函数 function globalFunction() {} console.log(globalThis.globalFunction); // function globalFunction() // ShadowRealm 里没有 console.log(shadow.evaluate('globalThis.globalFunction')); // undefined
// 在 ShadowRealm 里声明函数 shadow.evaluate('function secret() { return "hidden"; }'); // 主 realm 访问不到 console.log(globalThis.secret); // undefined // 但可以通过 shadow 访问 console.log(shadow.evaluate('globalThis.secret')); // function secret()
2. importValue() — 动态导入模块
// spookycode.js export function greeting() { return "Hello from the ShadowRealm!"; } // 主程序 { const shadow = new ShadowRealm(); // 导入模块并获取导出值 const shadowGreet = await shadow.importValue("./spookycode.js", "greeting"); console.log(shadowGreet()); // "Hello from the ShadowRealm!" }
安全边界说明
不是真正的安全边界:
- ShadowRealm 代码仍可推断其他 realm 的信息
- 提供完整性边界,而非安全边界
什么是完整性边界:
- 代码不能直接干扰其他 realm 的对象
- 除非你主动允许(通过函数绑定)
const shadow = new ShadowRealm(); // 返回一个函数,可以修改 ShadowRealm 内的全局变量 const setShadowValue = shadow.evaluate('(v) => globalThis.x = v'); setShadowValue("secret"); // 主 realm 不受影响 console.log(globalThis.x); // undefined // 但可以从 ShadowRealm 读取 console.log(shadow.evaluate('globalThis.x')); // "secret"
当前进度
| 状态 | 说明 |
|---|---|
| Stage 2.7 | 已批准原则,正在验证 |
| Stage 3 | 浏览器开始实现(未来) |
| Stage 4 | 纳入 ECMAScript 标准 |
注意: 目前还是提案,浏览器暂未实现。
使用场景
- 在"干净房间"运行测试套件,避免 mock 数据污染
- 隔离第三方库,防止全局污染
- 执行不信任代码(如插件系统)
- 无限多个一次性沙箱环境
核心结论
ShadowRealm 提供轻量级代码隔离,在主线程执行但不受全局污染影响。API 简洁(仅 evaluate + importValue),适合测试、插件、第三方库隔离等场景。目前已到 Stage 2.7,离浏览器实现不远了。