前端沙箱机制

目录

一、前端沙箱机制(Frontend Sandbox)概念(⭐️)

定义:前端沙箱是一种让"不可信代码"在浏览器中运行,但又不能影响宿主应用的隔离机制。

核心任务:在浏览器里运行 外部脚本微应用组件用户自定义脚本 而不破坏 宿主环境。

二、为什么需要前端沙箱?

前端越来越像操作系统,经常需要:

  • 微前端加载多个团队独立发布的应用
  • 低代码平台中用户随时写 JS 代码
  • 浏览器插件(SDK、广告、分析脚本)插入大量第三方代码
  • Web IDE、在线沙盒需要执行用户代码
  • 提升安全性,避免脚本污染全局变量或操作 DOM

若无沙箱,可能出现以下问题:

  • 修改 window 全局变量
  • 修改 DOM 导致 UI 崩溃
  • 偷 token / cookie
  • XSS 注入
  • 影响主应用的性能或路由

三、前端沙箱的三大核心目标(⭐️)

所有方案本质都围绕:

  • 隔离(Isolation):不影响主应用的变量、DOM、CSS、网络行为。
  • 限制(Restriction):限制在沙箱内的代码可访问的 API。
  • 监控(Observation):审计访问 window / DOM / 网络的行为。

1、隔离------避免互相污染

不影响主应用的变量、DOM、CSS、网络行为。

阻止子应用、插件或用户脚本:

  • 修改 window 全局变量
  • 修改 document / DOM
  • 修改宿主应用的样式
  • 覆盖宿主应用的函数

这是微前端、第三方脚本的核心需求。

2、限制------防止恶意脚本攻击

限制在沙箱内的代码可访问的 API。

沙箱可以限制脚本以营造安全的执行环境:

  • 不能访问敏感 API(如 cookie、本地存储)
  • 不能随意网络请求
  • 不能 DOM 注入
  • 不允许执行危险代码

例如:

  • 限制 eval
  • 禁止访问 window.document
  • 限制 fetch/XHR 的域名

重点在低代码平台、在线代码编辑器、用户输入代码的场景。

3、监控------限制能力范围

审计访问 window / DOM / 网络的行为。

让宿主(主应用)完全控制:

  • 子脚本能访问什么、不能访问什么
  • 子应用如何与主应用通信
  • 是否允许 DOM 操作
  • 是否允许网络请求
  • 是否允许写全局变量

这个在 插件系统(Plugin System) 中很常见。

四、前端常用的沙箱技术(按强度排序)(⭐️)

1、iframe 沙箱(最强)

浏览器原生提供,可以隔离:

  • JS 执行环境
  • DOM
  • CSS
  • 网络权限(使用 sandbox 属性可限制)

常见用法:

html 复制代码
<iframe src="sub-app.html" sandbox="allow-scripts allow-same-origin"></iframe>

优点:

  • 隔离最强、绝对安全
  • 浏览器级隔离

缺点:

  • 性能差(新 document 新全局环境)
  • 与主应用通信麻烦
  • DOM / 样式隔离太"硬"

典型使用:在线 IDE、微前端、很多广告系统

2、基于 Proxy + with 的运行时 JS 沙箱(Qiankun、乾坤常用)

现代微前端极常用。

简化示例:

typescript 复制代码
const sandbox = new Proxy({}, {
  get(_, key) {
    return window[key];
  },
  set(_, key, value) {
    // 写入到沙箱独立对象,而不影响真实 window
    sandbox[key] = value;
  }
});

with (sandbox) {
  eval(userScript);
}

隔离能力:

隔离
JS 全局变量 ✔ 强
DOM ❌ 无(仍能访问 document)
CSS

适合微前端场景:每个子应用互不污染 window。

3、Realm / ShadowRealm API(未来标准,安全更强)

ShadowRealm 是 TC39 提案,提供:

  • 全新的 JS 运行上下文
  • 不能直接访问宿主 window
  • 只能通过 API 显式传递

示例:

typescript 复制代码
const realm = new ShadowRealm();
realm.evaluate(`1 + 1`);

但目前兼容率还不够高。

4、构建期沙箱(静态沙箱)------------ AST 限制用户代码

对用户代码做编译处理:

  • 禁止访问 window
  • 禁止访问 document
  • 限制 import
  • 限制全局变量
  • 替换敏感 API

例如:

typescript 复制代码
const code = transform(`
  window.localStorage.clear()
`);

转换后:

typescript 复制代码
throw new Error("Forbidden API: window.localStorage");

在线低代码平台/云函数/代码编辑器常用

5、WASM(WebAssembly)沙箱

  • 将不可信代码编译为 WASM
  • WASM 运行在虚拟内存中
  • 无法访问 DOM、window、网络(必须显式绑定)

非常适合:

  • 插件执行
  • 后端逻辑在前端运行
  • 运行 Python/Rust 程序

五、微前端中的沙箱重点(重点难点)(⭐️)

在微前端体系(如 qiankun、wujie、single-spa)中,微前端沙箱核心问题:

  • JS 沙箱:不能污染 window
  • CSS 沙箱:不同子应用样式不互相覆盖
  • DOM 沙箱:DOM mount/unmount 需要自动恢复
  • Network 沙箱(难点):
    • 拦截 fetch/XHR
    • 防止子应用修改全局设置(如 axios.defaults)

Qiankun 用什么?

  • JS 沙箱:Proxy + with
  • CSS 沙箱:基于 scoped 样式 + 自动加前缀
  • DOM 沙箱:虚拟 DOM 区域挂载
  • 网络沙箱:patch fetch / xhr

六、前端沙箱可能被突破吗?(难点)

任何非 iframe 的沙箱都有被突破的可能

例如:

风险 示例
DOM Escape userScript 直接执行 document.body.remove()
原型链污染 userScript 修改 Array.prototype
访问 window 泄漏 提交函数指针、事件回调泄漏 window
CSS Escape :global { } 覆盖全局 CSS

所以:

Proxy + with 型的 JavaScript 沙箱 ≠ 安全沙箱,只能做隔离,不是安全机制。

七、如何构建一个"安全级"的前端沙箱?(含简版架构图)(⭐️)

必须组合以下方案:

  1. iframe 隔离运行环境(root 沙箱)
  2. 构建期 AST 限制访问(禁止危险 API)
  3. 运行时 Proxy 限制全局访问
  4. 网络访问限制
  5. CSS 隔离(shadowRoot)
  6. 配额限制(时间、内存)
  7. 输出白名单机制(event whitelist)

这才是"真正意义上的沙箱"。

最常用的前端沙箱架构图(简版):

八、前端沙箱的典型应用(按使用频率排序)

1、微前端(Micro-Frontend)(⭐️)

各团队独立开发的应用在同一个主应用中加载。

例如:

  • 主应用 + Vue 微应用
  • 主应用 + React 子应用
  • 主应用 + Angular 子应用

沙箱解决的核心问题是:

  • 子应用不能修改宿主应用的 window
  • 子应用的全局变量不能污染其他子应用
  • 样式隔离(CSS 不互相覆盖)
  • DOM mount/unmount 可控

qiankun、wujie 都基于沙箱机制。

2、低代码平台(Low-code)执行用户脚本(⭐️)

用户可以在浏览器里写:

typescript 复制代码
return form.age > 18;

这是高风险代码,必须沙箱隔离。

沙箱用途:

  • 禁止访问 window
  • 禁止操作 DOM
  • 限制请求域名
  • 只允许使用白名单 API

典型:富图表平台、低代码平台、流程编排系统。

3、在线代码运行(Code Runner / Playground)

例如:

  • 运行用户编写的 JS(JSBin、CodeSandbox)
  • 在线课程中运行 demo
  • 前端评测系统(如牛客网、力扣中的浏览器运行)

沙箱用途:

  • 为每个用户脚本创建独立上下文
  • 限制能力(不能访问 DOM、不能操作 cookie)
  • 捕获异常、输出结果

4、第三方脚本隔离(SDK / 广告 / 分析)

例如:

  • Google Analytics
  • Chat 插件
  • 广告脚本(广告联盟)
  • 第三方组件库(表单、播放器、图表)

不可信的第三方 JS 可能会:

  • 修改 window 原型
  • 覆盖 console
  • 修改样式
  • 注入 iframe
  • 泄漏 token

沙箱隔离能防御大部分风险。

5、插件系统(Plugin System)

例如:

  • VSCode 的 Web 版插件
  • Figma 插件
  • Notion 插件
  • 自研系统的插件生态

插件来自第三方,不可信,需要:

  • 定义能访问的 API
  • 限制 DOM、网络
  • 独立 JS runtime

一般用 iframe 或 ShadowRealm 沙箱。

6、业务系统中的"动态脚本功能"

用户可以在系统里写公式、脚本,例如:

  • 表单规则(校验规则用 JS 写)
  • 动态事件(button.onClick 使用 JS 回调)
  • 可配置工作流(workflow 里的脚本节点)
  • 动态主题 / 动态样式

必须使用沙箱执行,避免:

  • 用户脚本修改全局变量
  • DOM 破坏
  • XSS 攻击

7、WebAssembly(WASM)隔离执行第三方逻辑

例如:

  • 加载 Rust、Go、C# 编译成 WASM 的插件
  • 不可信的 CPU 密集运算
  • 视频编码器 / 压缩库

WASM 本身就带沙箱,但仍需围绕宿主增加控制。