|
1 |
| -# secure-vm |
| 1 | +<div align="center"> |
2 | 2 |
|
3 |
| -一个利用浏览器实现的,安全、轻量、极简、透明的沙箱环境。 |
| 3 | +# ⭐ secure-vm |
4 | 4 |
|
5 |
| -```js |
6 |
| -const ctx = vm() |
7 |
| -ctx.console = console |
8 |
| -ctx.eval('console.log("Hello World!")') |
9 |
| -``` |
| 5 | +> 🧪 Experimental `vm()` based on iframe for frontend (electron, micro apps, etc). |
10 | 6 |
|
11 |
| -- [secure-vm](#secure-vm) |
12 |
| - - [兼容性](#兼容性) |
13 |
| - - [使用方法](#使用方法) |
14 |
| - - [创建](#创建) |
15 |
| - - [外部访问](#外部访问) |
16 |
| - - [缓存](#缓存) |
17 |
| - - [原理](#原理) |
| 7 | +</div> |
18 | 8 |
|
19 |
| -## 兼容性 |
| 9 | +## 📃 Getting Started |
20 | 10 |
|
21 |
| -| 特性 | Chrome | Edge | Firefox | Safari | Opera | |
22 |
| -| -------- | ------ | ---- | ------- | ------ | ----- | |
23 |
| -| 沙箱支持 | 84 | 84 | 79 | 14.1 | ❌ | |
| 11 | +### 🔽 Install |
24 | 12 |
|
25 |
| -## 使用方法 |
| 13 | +#### 🦊 npm, yarn & pnpm, etc. |
26 | 14 |
|
27 |
| -### 创建 |
| 15 | +```bash |
| 16 | +npm install secure-vm |
| 17 | +yarn add secure-vm |
| 18 | +pnpm install seucre-vm |
| 19 | +``` |
28 | 20 |
|
29 |
| -要创建一个上下文,方式如下: |
| 21 | +#### 👾 IIFE (not recommended) |
30 | 22 |
|
31 |
| -```js |
32 |
| -const ctx = vm() // 返回一个 globalThis 对象 |
| 23 | +```html |
| 24 | +<script src="index.global.js"></script> |
| 25 | +<script> |
| 26 | + const ctx = SecureVM.vm() |
| 27 | +</script> |
33 | 28 | ```
|
34 | 29 |
|
35 |
| -然后,你可以使用 `ctx.eval` 或者 `ctx.Function` 执行代码: |
| 30 | +### ✅ Usage |
36 | 31 |
|
37 | 32 | ```js
|
38 |
| -ctx.eval('1 + 1') |
| 33 | +import { vm } from 'secure-vm' |
| 34 | + |
| 35 | +const ctx = vm() // Create an isolated context. |
| 36 | +ctx.console = globalThis.console |
| 37 | +ctx.eval(` |
| 38 | +console.log("Hello secure-vm") |
| 39 | +`) |
39 | 40 | ```
|
40 | 41 |
|
41 |
| -整个框架就这么多内容。 |
| 42 | +## 🐺 Compatibility |
| 43 | + |
| 44 | +☣️ This is an **experimental library** that may be incompatible with some old browser kernels (for example, Opera). |
| 45 | + |
| 46 | +💫 Try it out by yourself: (Demo not ready) |
42 | 47 |
|
43 |
| -### 外部访问 |
| 48 | +## 🛠️ Features |
44 | 49 |
|
45 |
| -你可以通过 `ctx` 向沙盒本身添加或移除一些全局属性,secure-vm 会帮助你进行相应的隔离。 |
| 50 | +<table> |
| 51 | +<tr><td> |
46 | 52 |
|
47 |
| -甚至,即使使用 `ctx.Function = Function`,也不会导致沙盒逃逸。 |
| 53 | +### 🔰 Ease to use |
48 | 54 |
|
49 |
| -**警告:secure-vm 并不能保证外部内容不被滥用。如果你的函数含有 eval 或者 Function 等内容,即使 secure-vm 也无能为力。** |
| 55 | +✅ To create a simple isolation, you only have to use a simple function, `vm`. |
50 | 56 |
|
51 | 57 | ```js
|
52 |
| -function A() { |
53 |
| - this.method = function () { |
54 |
| - return new Function("return 'Hello World'") |
55 |
| - } |
56 |
| - this.set_value = function (value) { |
57 |
| - this.value = value |
58 |
| - } |
59 |
| - this.value = new Object() |
60 |
| -} |
61 |
| -const instance = new A() |
62 | 58 | const ctx = vm()
|
63 |
| -ctx.instance = instance |
64 |
| -ctx.eval(` |
65 |
| -const instance2 = new instance.constructor(); // OK,将创建一个新的,受隔离的 instance。 |
66 |
| -instance.method()(); // OK,将返回 Hello World。 |
67 |
| -instance2.method()(); // OK,将返回 Hello World。 |
68 |
| -instance.method().constructor('return window')(); // 逃逸失败 |
69 |
| -instance.value.constructor.constructor('return window')(); // 逃逸失败 |
70 |
| -instance2.value.constructor.constructor('return window')(); // 逃逸失败 |
71 |
| -instance.set_value(1); // 成功 |
72 |
| -instance2.set_value(1); // 成功 |
| 59 | +``` |
| 60 | + |
| 61 | +<img width=2000 /> |
| 62 | + |
| 63 | +</td></tr> |
| 64 | +<tr><td> |
| 65 | + |
| 66 | +### 🔒 Security |
| 67 | + |
| 68 | +🥰 Feel free to add anything you want, `Function` (`constructor`) is gonna be safe. |
| 69 | + |
| 70 | +```js |
| 71 | +ctx.fetch = fetch |
| 72 | +ctx.console = console |
| 73 | +fetch('some furry pics') |
| 74 | + .then( |
| 75 | + ctx.eval(` |
| 76 | +req => { |
| 77 | + console.log(req) |
| 78 | + return req.text() |
| 79 | +} |
73 | 80 | `)
|
| 81 | + ) |
| 82 | + .then(v => { |
| 83 | + console.log(v) |
| 84 | + }) |
74 | 85 | ```
|
75 | 86 |
|
76 |
| -## 缓存 |
| 87 | +</td></tr> |
| 88 | +<tr><td> |
| 89 | + |
| 90 | +### 🤔 Obfuscation |
77 | 91 |
|
78 |
| -为了确保引用比较相等且不引发错误,secure-vm 内置了缓存系统,将尽量减少 Proxy 的创建。 |
| 92 | +🔏 secure-vm will automatically erase the traceback line info (if available) so hackers cannot access source code, making it harder to deobfuscate. |
79 | 93 |
|
80 | 94 | ```js
|
81 |
| -const ctx = vm() |
82 |
| -const a = { |
83 |
| - array1: ctx.Array, |
84 |
| - array2: ctx.Array |
| 95 | +ctx.eval(` |
| 96 | +function throwError() { |
| 97 | + throw new Error('Where is it?') |
85 | 98 | }
|
86 |
| -console.log(a.array1 === a.array2) // true |
87 |
| -delete a.array1 |
88 |
| -delete a.array2 |
89 |
| -// 此处,Proxy 对象被回收 |
| 99 | +throwError() // throwError() will not be displayed in the DevTools traceback (Edge, Chromium, Firefox). |
| 100 | +`) |
90 | 101 | ```
|
91 | 102 |
|
92 |
| -## 原理 |
| 103 | +</td></tr> |
| 104 | +</table> |
| 105 | + |
| 106 | +--- |
93 | 107 |
|
94 |
| -iframe 在被加入 DOM 树时,会生成一个 Window 对象放置于 iframe.contentWindow。 |
| 108 | +<div align="center"> |
95 | 109 |
|
96 |
| -当 iframe 被从 DOM 树删除时,iframe.contentWindow 将变为 null。 |
| 110 | +_`This project is licensed under the MIT license.`_ |
97 | 111 |
|
98 |
| -而如果在删除之前先使用变量引用 contentWindow,再去删除 iframe,则会得到一个资源都被释放,但各种基础函数仍可用的 iframe。 |
| 112 | +❤️ |
99 | 113 |
|
100 |
| -这将成为一个绝佳的沙盒环境。secure-vm 在其上配合 Proxy,实现了前端安全沙盒。 |
| 114 | +</div> |
0 commit comments