# a-sandbox
**Repository Path**: ambit/a-sandbox
## Basic Information
- **Project Name**: a-sandbox
- **Description**: 一款安全的、同步的、兼容良好的、支持定制的浏览器沙箱
- **Primary Language**: TypeScript
- **License**: MulanPSL-2.0
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2022-09-20
- **Last Updated**: 2024-10-14
## Categories & Tags
**Categories**: Uncategorized
**Tags**: 沙箱, sandbox, shadowrealm, js-sandbox, web-sandbox
## README
# A Sandbox
本沙箱借鉴了 ShadowRealm API 的设计思路,严格限制沙箱内外交互的数据类型,以保证良好的隔离性与安全性,并针对其不满足需求的地方做了扩展设计,如:允许用户自行定制、允许传递`Promise`等。
✨ 在线试用一下
## Features
1. 沙箱内外交互允许的数据类型有原始类型(Primitive)、函数类型(Callable)、`Promise`类型,以及可被结构化克隆的数据(如:`Array`、`Blob`、`Date`、`Int8Array`等);
1. 除了 ECMA-262 规范中定义的全局对象外,还默认支持部分浏览器环境的对象,如`atob`、`Crypto`、`TextEncoder`、`URL`等,不会对沙箱外产生副作用;
1. 允许用户自行定制,通过钩子`onInit`可以拿到`realm`对象,`realm`保存着沙箱内部使用的数据(如:全局对象、`iframe`等);
1. 兼容性极佳,编译输出的代码为 **ES5**,并且对所有用到的比 ES5 新的 API 都做了兼容处理;
## Install
```shell
npm install a-sandbox
```
## Usages
```ts
export default class Sandbox {
constructor(options?: {
onInit: (realm: Realm) => void;
});
/**
* Eval code string in sandbox
* @return callable, structured or promise data
*/
evaluate(sourceText: string): any;
/**
* Run function in sandbox
* @return the same as `evaluate`
*/
evaluateHandle(func: (this: undefined) => any): any;
}
```
- 在沙箱中执行代码
```ts
import Sandbox from "a-sandbox";
const aSandbox = new Sandbox();
aSandbox.evaluate(`
console.log(globalThis); // sandbox's global object
`);
aSandbox.evaluateHandle(() => {
console.log(globalThis); // sandbox's global object
});
```
- 自行定制:允许沙箱内使用`localStorage`
```ts
import Sandbox, { Realm } from "a-sandbox";
const aSandbox = new Sandbox({ onInit });
function onInit(realm: Realm){
realm.globalObject.localStorage = realm.intrinsics.localStorage;
}
```
`realm`保存着沙箱内部使用的数据,需谨慎操作。其中,`globalObject`值为沙箱的全局对象,沙箱关联的`iframe`的初始全局对象的属性值备份在`intrinsics`对象上。
- 自行定制:向沙箱中注入全局变量
```ts
import Sandbox, { Realm } from "a-sandbox";
const aSandbox = new Sandbox({ onInit });
function onInit(realm: Realm){
const createPostMyMessage = realm.intrinsics.eval(`
(cb) => function(){ return cb(arguments) }
`);
realm.globalObject.postMyMessage = createPostMyMessage(onMyMessage);
}
function onMyMessage(args: any[]) {
console.log(args);
}
```
> ⚠️ 进行定制时,**不能**将外部的对象泄漏到沙箱中,防止沙箱中的代码通过**原型链**对外部进行攻击。
在上述的代码中,先通过沙箱中的`eval`生成安全的工厂函数,再将外部的`onMyMessage`作为入参传给工厂函数生成`postMyMessage`函数,沙箱中以闭包的形式来安全地调用外部函数`onMyMessage`。
## Contact
1. 邮箱: ambit_tsai@qq.com
1. 微信: cai_fanwei
1. QQ群: 663286147