@web-sandbox.js/web-sandbox
Version:
172 lines (121 loc) • 5.48 kB
Markdown
# WebSandbox
> WebSandbox 基于 Realm Stage 2 规范实现,前一段时间 Realm 进入了 Stage 3,它有了非常大的 API 变更,这使得 WebSandbox 需要重新进行适配。
WebSandbox 的目标是构建一个安全且轻量化的浏览器虚拟化容器,它采用使用 Web 标准技术来构建,它的使用场景:
* 作为 Web 应用的插件的安全运行环境、提供开放式的插件系统
* 让不同的技术栈、版本的组件能够在同一个页面中运行,避免陷入重构的泥潭
[https://web-sandbox.js.org/](https://web-sandbox.js.org/)
## 安全模型
* JS 语言安全——Realm: 基于 TC39 最新草案实现
* CSS 安全——Shadow DOM: Web 正式标准
* HTML 安全——Sanitizer: 基于 W3C 草案实现
* 内容安全策略——CSP: 基于 W3C 正式标准实现
## 资源虚拟化
### DOM 树
WebSandbox 拥有完整的 DOM 树结构,这些使用 ShadowRoot 隔离。
```html
<web-sandbox> ——— window
#shadow-root ——— document
<html> ——— document.documentElement
<head></head> ——— document.head
<body></body> ——— document.body
</html>
</web-sandbox>
```
### 内容安全策略
可以通过 CSP 配置来控制应用内部的脚本、样式、链接、表单、网络请求等行为。
```html
<web-sandbox
name="sandbox-evaluate"
csp="
default-src 'none';
script-src 'self' 'unsafe-inline' 'unsafe-eval' cdn.jsdelivr.net;
style-src * 'unsafe-inline' cdn.jsdelivr.net;
navigate-to 'self' web-sandbox.js.org;
">
</web-sandbox>
```
### 本地存储
拥有专属的本地存储空间,主文档或者父 WebSandbox 可以对它进行管理。
```html
<web-sandbox
id="box"
text="
localStorage.setItem('test', 1)
">
</web-sandbox>
```
### Web Components
拥有完整的 Web Components 虚拟化实现,WebSandbox 内部注册的自定义元素不会影响主文档。
### Viewport
WebSandbox 中的 CSS 无法影响主文档,包括设置了 `position: fixed` 元素、`:host` 选择器。
### Task
`requestAnimationFrame()`、`setTimeout()`、`setInterval()` 等异步任务将随着 WebSandbox 销毁而自动结束。
### ChildWebSandbox
WebSandbox 的应用内部也可以使用 WebSandbox,并且将继承内容安全策略。
```html
<web-sandbox
id="box"
text="
const sandbox = document.createElement('web-sandbox');
sandbox.src = './child.js';
document.body.appendChild(sandbox);
">
</web-sandbox>
```
## 标签
```html
<web-sandbox name="application-name" src="https://cdn.jsdelivr.net/npm/application-name@3/dist/web-sandbox-application.demo.js">
</web-sandbox>
```
## 属性
### name
沙箱应用名称。该名称可以用作为沙箱内 `window.name` 的值(也将作为内部分配本地缓存资源的命名空间)。
### src
远程沙箱脚本地址。
### text
本地的脚本内容。
### contentWindow
沙箱内的 `window` 对象。只有在 `<web-sandbox>` 插入到文档后才可以访问到。
### contentDocument
沙箱内的 `document` 对象。只有在 `<web-sandbox>` 插入到文档后才可以访问到。
### csp
内容安全策略。CSP 可以精细化的指定沙箱的运行权限,例如限制数据请求等、禁止运行远程脚本等。这是 [CSP](https://www.w3.org/TR/CSP2/) 规范的子集。
如果不设置 `csp` 属性,那么 `<web-sandbox>` 将会启用默认指令 `default-src none`。
支持的指令:
* `default-src`
* `connect-src`
* `script-src`
* `style-src`
* `form-action`
* `navigate-to`
`source` 支持的关键字:
* `'none'`
* `'self'`
示范:
```html
<web-sandbox
name="sandbox-evaluate"
title="WebSandbox View"
csp="
default-src 'none';
script-src 'self' 'unsafe-inline' 'unsafe-eval' cdn.jsdelivr.net;
style-src * 'unsafe-inline' cdn.jsdelivr.net;
navigate-to 'self' web-sandbox.js.org;
">
</web-sandbox>
```
更多 CSP 介绍:<https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP>
## 限制
* 受 Realm 垫片实现影响,远程的脚本与样式必须允许同源访问
* 受 Realm 垫片实现影响,脚本中在严格模式下运行
* 受 Realm 垫片实现影响,影响,脚本中不能包含 HTML 注释语句 `<!--->`
* 受 Realm 垫片实现影响,影响,脚本中不能使用 ES6 `import` 导入模块
* 受 Realm 垫片实现影响,影响,脚本中不能**直接**使用 `eval()` 语句;允许**间接**使用,例如 `(0, eval)(code)`。这个限制会导致一些依赖 `eval()` 语句动态编译模板的框架无法运行,这些模板必须在构建阶段编译后才能运行,例如 Vue
* 受内置安全策略影响,不能使用主文档定义好的自定义元素
* 受内置安全策略影响,脚本通过 `element.innerHTML` 等类似的 API 插入内容的时候可能会被过滤掉有危险的标签与属性
* 受内置安全策略影响,主文档无法通过 `localStorage` 给沙箱脚本共享数据,因为 `localStorage` 被隔离
* 受内置安全策略影响,无法捕获脚本运行时的全局错误,只允许主文档捕获
* 不支持 CSS 的 vw/vh 单位
* 不支持 CSS 媒体查询
* 不支持 CSS 的 `import` 语句导入样式
受安全策略与项目进展的影响,浏览器的 API 以白名单的方式提供,细节请查阅 [Web API 兼容性报告](https://web-sandbox.js.org/docs/web-compat/)。