49

我希望能够让用户提交任意 JavaScript 代码,然后将其发送到 Node.JS 服务器并在输出发送回多个客户端(作为 JSON)之前安全地执行。eval想到了这个函数,但我知道这有多个安全问题(用户提交的代码将能够访问 Node 的文件 API 等)。我见过一些项目,如 Microsoft Web Sandbox 和 Google Caja,它们允许执行经过清理的标记和脚本(用于在网站上嵌入第三方广告),但似乎这些是客户端工具,我不确定它们是否可以在 Node.js 中安全使用。

是否有一种标准方法可以在 Node 中沙箱并执行不受信任的 JavaScript 以获取输出。尝试在服务器端执行此操作是错误的吗?

编辑:用户能够利用 JavaScript 的全部功能并不重要,事实上,最好能够选择哪些 API 将提供给用户代码。

编辑:我将继续更新我发现的内容。这个 Sandcastle 模块 ( bcoe/sandcastle) 似乎旨在完成我的想法。不知道它有多安全,但因为我这不是什么太重要的事情,我想我会尝试一下。如果我能够成功地做到这一点,我会添加我自己的答案。

4

5 回答 5

12

您可以通过 vm.runInContext('js code', context) 在 nodejs 中使用沙箱支持,api 文档中的示例:

https://nodejs.org/api/vm.html#vm_vm_runinthiscontext_code_options

const util = require('util');
const vm = require('vm');

const sandbox = { globalVar: 1 };
vm.createContext(sandbox);

for (var i = 0; i < 10; ++i) {
    vm.runInContext('globalVar *= 2;', sandbox);
}
console.log(util.inspect(sandbox));

// { globalVar: 1024 }

警告:正如“s4y”所指出的,它似乎有缺陷。请看评论。

于 2015-01-13T19:06:26.730 回答
6

一种替代方法是使用http://github.com/patriksimek/vm2

$ npm install vm2

然后:

const {VM} = require('vm2');
const vm = new VM();

vm.run(`1 + 1`);  // => 2

如其他答案的评论中所述。

我不知道它有多安全,但它至少声称它安全地运行不受信任的代码(在其自述文件中)。就此处其他答案中建议的解决方案而言,我找不到任何明显的安全问题。

于 2018-01-01T12:26:35.313 回答
5

此答案已过时,因为 gf3 不提供针对沙盒破坏的保护

http://gf3.github.io/sandbox/ - 它使用require('child_process')而不是require('vm').

于 2013-07-07T16:25:48.000 回答
5

在 Node.js 下,您可以创建一个沙盒子进程,但您还需要在代码后面附加"use strict";,否则可能会破坏沙盒arguments.callee.caller

不确定为什么需要将其发送到服务器,因为代码也可能在沙盒网络工作者中执行。

还可以看看我的Jailed库,它简化了刚才提到的 Node.js 和 Web 浏览器的所有内容,还提供了将一组函数导出到沙箱的机会。

于 2014-09-18T16:59:14.763 回答
2

根据您的使用情况,我建议您还考虑使用 gVisor 等虚拟环境保护您的沙箱。你可以在这里找到一些信息。

于 2019-10-07T22:39:50.703 回答