在服务器上以沙盒方式运行不受信任的JavaScript代码

7
我似乎无法弄清如何设置一个可以安全运行不受信任代码的节点沙盒,并允许用户通过API调用与程序进行交互(系统输入和输出)。我正在尝试在浏览器中设置控制台,以便用户可以从服务器上运行自己的代码。
是否有任何支持此功能的节点包,或者我需要编写自己的节点VM?谢谢。
编辑:我希望用户能够编写readline()并使程序在断点处等待数据传输。同样,console.log()的输出应重定向到输入API调用的响应。

也许可以使用Nodejs VM模块?但是,如果您想要完全的沙盒安全性,则可能需要在实际隔离的VM中运行一个新的nodejs进程。此外,如何在node.js沙盒中安全地运行用户提交的脚本? - jfriend00
是的,我有一个正在运行的服务器,其中包含用户的代码。当用户在客户端上发出API请求以运行程序时,我希望虚拟机运行它。如果有readline,则程序应暂停并等待,响应客户端的任何sys out数据都会在断点之前生成,并且应告诉客户端需要输入。当用户输入时,程序恢复执行,直到下一个输入或程序结束。在任何情况下,API响应都将具有sys out。 - X88B88
我仍然不明白你期望从哪里获取readline()的输入。如果用户是远程的,他们与任何服务器进程的标准输入都没有连接。因此,如果您想向进程提供来自最终用户的某些内容,则必须有人构建一个应用程序或页面,从用户那里获取该输入并将其馈送到服务器。这可能是用户在第一次运行程序时与之交互的任何页面的工作。有许多可能的方法来做到这一点,但我不了解您正在进行的整体性质,无法知道要推荐什么。 - jfriend00
我已经建立了一个页面,可以从用户那里获取数据并将其传递给服务器。我只需要一种安全地在服务器上运行程序的方法。我基本上想模拟标准输入(stdin),并传入从客户端接收到的数据。 - X88B88
1
这回答解决了你的问题吗?如何在服务器端运行不受信任的代码? - Jerska
显示剩余4条评论
1个回答

3
您可以使用 vm2 模块以安全的方式运行任何带有用户输入的代码。
您甚至可以定义用户提供的代码是否有权访问原生 Node 模块或其他模块(通过相对路径),或者定义来自用户输入的代码是否可以进行外部调用。
您可以在 try/catch 中捕获和执行此“不受信任”的代码,以观察灾难性故障,甚至设置超时时间,使此运行不会过度负荷。
快速示例:
const {VM} = require('vm2');
const vm = new VM();

vm.run(`process.exit()`); // TypeError: process.exit is not a function

使用内置的“request”模块访问外部资源。
const {NodeVM} = require('vm2');
const vm = new NodeVM({
    require: {
        external: true // allow all modules or use Array for one e.g: ['request']
    }
});    

vm.run(`
    var request = require('request');
    request('http://www.google.com', function (error, response, body) {
        console.error(error);
        if (!error && response.statusCode == 200) {
            console.log(body) // Show the HTML for the Google homepage.
        }
    })
`, 'vm.js');

默认情况下,该条目被编译为 javascript,但您可以传递一个带有自定义编译器的函数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接