nodejs: run module in sandbox

后端 未结 1 714
时光取名叫无心
时光取名叫无心 2021-01-28 06:21

I have this turn-based NodeJs gaming app in which developers (anyone) can submit a player-robot. My NodeJS app will load all players and let them play against each other. Becaus

相关标签:
1条回答
  • 2021-01-28 06:56

    Don't do this yourself. Use an existing library. There are quite a few issues you have to deal with if you were to write it yourself. For example: How do you handle a user writing a never ending for-loop?

    How to run untrusted code serverside?


    If you are planning on writing it yourself then yes, you will need the vm module.

    By passing in an empty "sandbox" you have removed all global variables.

    script.runInNewContext({});
    

    Next you'll need to figure out how you want to handle the never ending for-loop. You'll have to create a new process to handle this scenario. Do you create 1 process to manage ALL untrusted code? If you do then you'll have to kill ALL untrusted code if a single script hangs. Do you create a new process for each untrusted code? If you do then you won't be happy with performance. Creating a new process can take a second or two. You could require the child process to "notify" the main process it's still alive. If it fails to notify within 5 seconds (or whatever your threshold is, kill the process). Note: script.runInNewContext does contain an option that lets you specify a "timeout" (if the code takes longer than X seconds - throw an exception), but the problem with that is it allows async code (according to another Stackoverflow post), although you could defend against that by not introducing setTimeout, setInterval, or setImmediate into the scope. However, even if you set it to 1 second, NO other code can run during that second in that process. So if you have 1000 scripts to run, it could take up to 1000 seconds (16 minutes) to run them all. At least running each in their own process will let them run in parallel.

    Here's an example of why the timeout option won't work for you:

    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');
    

    Next you'll need to figure out how to communicate from your main process, into a child process and then into the vm. I'm not going to get into communicating between processes as you can find that pretty easily. So, by calling script.runInNewContext you are executing the code right then and there. Which lets you set global variables:

    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');
    
    0 讨论(0)
提交回复
热议问题