javascript 如何在 node.js 沙箱中安全地运行用户提交的脚本?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7446729/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 00:10:03  来源:igfitidea点击:

How to run user-submitted scripts securely in a node.js sandbox?

javascriptnode.jsv8

提问by broofa

What are the options for running (possibly malicious) user-submitted scripts in node.js, securely? I.e. in an environment that prevents code from accessing sensitive data and APIs?

在 node.js 中安全运行(可能是恶意的)用户提交的脚本有哪些选项?即在阻止代码访问敏感数据和 API 的环境中?

vm.runInNewContext(userScript, {})is a tempting starting point... but it seems like there are known issuesthere.

vm.runInNewContext(userScript, {})是一个诱人的起点……但似乎那里存在已知问题

The sandbox modulelooks interesting, but uses runInNewContext()as well so I'm a bit leery of it.

沙箱模块看起来很有趣,但使用runInNewContext()也使我的有点持怀疑态度。

采纳答案by Laurent Perrin

You should always run untrusted code in a separate process, which is exactly what the sandbox module does. A simple reason is that vm.runInNewContext('while(true){}', {})will freeze node.

您应该始终在单独的进程中运行不受信任的代码,这正是沙箱模块所做的。一个简单的原因是vm.runInNewContext('while(true){}', {})会冻结节点。

It starts by spawning a separate process, which will later send the result serialized to JSON on its stdout. The parent process continues executing regardless of what the child does and can trigger a timeout.

它首先生成一个单独的进程,该进程稍后将在其标准输出上发送序列化为 JSON 的结果。无论子进程做什么,父进程都会继续执行,并且可以触发超时。

The untrusted code is then wrapped in a closure with strict mode(in regular JavaScript, you can use arguments.callee.callerto access data outside of your scope). Finally, a very limited globalobject is passed to prevent access to node's API. The untrusted code can only do basic computation and has no access to files or sockets.

然后将不受信任的代码封装在一个严格模式的闭包中(在常规 JavaScript 中,您可以使用它arguments.callee.caller来访问范围之外的数据)。最后,global传递了一个非常有限的对象以防止访问节点的 API。不受信任的代码只能进行基本计算,无法访问文件或套接字。

While you should read sandbox's code as an inspiration, I wouldn't recommend using it as is:

虽然您应该阅读沙箱的代码作为灵感,但我不建议按原样使用它:

  • The code is getting old and hasn't been updated for 7 months.
  • The Child Process module in node already provides most of the features you need, especially child_process.fork().
  • The IPC channel provided by child_process.fork probably has better performances.
  • 代码老了,7个月没更新了。
  • node 中的 Child Process 模块已经提供了您需要的大部分功能,尤其是child_process.fork()
  • child_process.fork 提供的 IPC 通道可能有更好的性能。

For increased security, you could also consider using setuid-sandbox. It's the code used by Google Chrome to prevent tab processes from accessing the file system. You would have to make a native module, but this exampleseems straightforward.

为了提高安全性,您还可以考虑使用setuid-sandbox。这是谷歌浏览器用来防止标签进程访问文件系统的代码。您必须制作一个本机模块,但这个例子看起来很简单。

回答by Alan Mimms

There is a newer module on github called vm2that addresses some of these concerns, especially in Node.JS applications. Maybe that will help some others find it, as I have just done.

github 上一个名为 vm2 的较新模块可以解决其中的一些问题,尤其是在 Node.JS 应用程序中。也许这会帮助其他人找到它,就像我刚刚所做的那样。