javascript - Node : run module in sandbox

标签 javascript node.js sandbox

我有一个基于回合的 NodeJs 游戏应用程序,开发人员(任何人)都可以在其中提交玩家机器人。我的 NodeJS 应用程序将加载所有玩家并让他们互相对战。因为我对提交的代码一无所知,所以我需要在沙箱中运行它。

例如,以下不受信任的代码可能如下所示:

let history = [];

export default class Player {
    constructor () {
        this.history = [];
    }

    move (info) {
        this.history.push(info);
   }

   done(result) {
       history.push({result: result, history: this.history});
   }
}

现在,在我的主应用程序中,我想做类似的事情

import Player1 from 'sandbox/player1';
import Player2 from 'sandbox/player2';
....

for (let outer = 0; outer < 10; outer ++) {
    let player1 = creeateSandboxedInstance(Player1);
    let player2 = creeateSandboxedInstance(Player2);
    for(let inner = 0; inner < 1000000; inner ++) {
        ...
        let move1 = player1.move();
        let move2 = player2.doMove();
        ...
    }
}

我希望 sandbox/createSandboxedInstance 环境负责的是:

  • 玩家类不应授予对文件系统/互联网的访问权限
  • 玩家类不应有权访问应用全局变量
  • 任何状态都应该重置(例如类变量)
  • 可能还有更多事情:)

我认为我应该使用vm module 。大概是这样的:

var vm = require('vm');

var script = new vm.Script('function move(info){ ... } ...', {conext});

var sandbox = script.runInNewContext();

script.move(..);  // or
sandbox.move(..);

但是,我无法让它工作,以便我可以调用 move 方法。类似的事情有可能吗?

最佳答案

不要自己这样做。使用现有的库。如果您自己编写,则必须处理很多问题。例如:如何处理用户编写永无止境的 for 循环?

How to run untrusted code serverside?

<小时/>

如果您打算自己编写它,那么是的,您将需要 vm 模块。

通过传入一个空的“沙箱”,您已经删除了所有全局变量。

script.runInNewContext({});

接下来,您需要弄清楚如何处理永无休止的 for 循环。您必须创建一个新流程来处理这种情况。您是否创建 1 个进程来管理所有不受信任的代码?如果这样做,那么如果单个脚本挂起,您将不得不杀死所有不受信任的代码。您是否为每个不受信任的代码创建一个新进程?如果你这样做,那么你将不会对表现感到满意。创建新进程可能需要一两秒钟的时间。您可以要求子进程“通知”主进程它仍然存在。如果它未能在 5 秒内通知(或无论您的阈值是什么,请终止该进程)。注意: script.runInNewContext 确实包含一个选项,允许您指定“超时”(如果代码花费的时间超过 X 秒 - 引发异常),但问题是它允许异步代码(根据另一篇 Stackoverflow 文章),尽管您可以通过不在作用域中引入 setTimeoutsetIntervalsetImmediate 来防范这种情况。但是,即使将其设置为 1 秒,该进程中的该秒内也无法运行其他代码。因此,如果您有 1000 个脚本要运行,则运行所有脚本可能需要长达 1000 秒(16 分钟)的时间。至少在自己的进程中运行每个进程将使它们并行运行。

以下示例说明了超时选项对您不起作用的原因:

var script = new vm.Script('move = function move(info) { for(var i = 0; i < 100000; i++) { console.log(i); } }');
var sandbox = { move: null, console: console };
var result = script.runInNewContext(sandbox, { timeout: 1 });
sandbox.move('woah');

接下来,您需要弄清楚如何从主进程通信到子进程,然后再通信到虚拟机。我不打算讨论进程之间的通信,因为您可以很容易地发现这一点。因此,通过调用 script.runInNewContext,您可以立即执行代码。它允许您设置全局变量:

var script = new vm.Script('move = function move(info) { console.log("test: " + info); }');
var sandbox = { move: null, console: console };
var result = script.runInNewContext(sandbox);
sandbox.move('success');

关于javascript - Node : run module in sandbox,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32113509/

相关文章:

javascript - 如何在 HTML 中淡入/淡出背景音乐(无 Flash)?

javascript - Canvas 调整大小-IOS HTML5 应用程序-(图表 JS)

javascript - 从 Node js中的文件读取序列化的对象数组

javascript - Cloud Functions Cloud Firestore 触发器

ios - 无需越狱访问应用程序文件夹

objective-c - 使用 ScriptingBridge 从另一个沙盒应用程序中编写 AppleScripting 沙盒应用程序

javascript - JSON api时间戳+数据解析

javascript - Highcharts箱线图图表定制

regex - Node.js 解析字符串中的数字

java - SecureAST定制器 : how to restrict loops?