Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set a maximum execution time of a script with node.js?

I give my users a flexible way to transform data using JavaScript, executed with Node.js on server-side. With that design, there is 3 issues to consider :

  • Security : I solved the security issue using a sandbox to avoid usage of native Node.js libraries.

  • Resources : we can easily set maximum memory usage using v8 option --max_executable_size. About the CPU usage, I'll see how to manage it using cpulimit or renice, it does not really matter now.

  • Time : I need to limit execution time of my scripts, to avoid them running as hangry zombies. And here I get stuck.

I tried something like :

 node -e '
    setTimeout(function() {
       console.log("timeout");
       process.exit;
    }, 5000);
    console.log("begin");
    while (1);
 '

But this code displays only "begin", it seems that my timeout is never called. Any idea ?

like image 512
Alain Tiemblo Avatar asked Mar 02 '13 16:03

Alain Tiemblo


3 Answers

You might want to look at tripwire (https://github.com/tjanczuk/tripwire). It is a module that can kill runaway node scripts and you can set a timeout. It is a native node module, so that is one thing to consider, but it works on Mac, Windows and Linux.

like image 177
Glenn Block Avatar answered Nov 15 '22 06:11

Glenn Block


Unfortunately, if your users can initiate blocking operations (like while(1)), there's no way to tell Node to exit after a certain time, as the blocking operation will prevent the setTimeout handler from firing. Either ensure that user-initiated stuff won't block the main loop, or (and this is a very bad idea) use some sort of external auto-kill/timeout to destroy the Node process.

Basically, you can use Node to limit the execution time of nonblocking code, but the whole point of Node is that blocking code blocks everything. If your users are truly capable of running arbitrary code, I'd consider running your process manager/timeout-killer at a higher level: for example, spawning processes with kill timeouts using Node's exec facility.

like image 42
Zac B Avatar answered Nov 15 '22 07:11

Zac B


Node's built-in vm module offers module.evaluate, script.runInContext and several other methods which will run code in a sandboxed environment and which take a timeout option to specify the maximum time (in ms) to allow the VM to run for.

Do note that running untrusted code in Node.js is fraught with potential security issues. Even the VM module specifically says "The vm module is not a security mechanism. Do not use it to run untrusted code." (Why not? Here is one reason why not: it looks like it should be harmless to run vm.runInNewContext("this.constructor.constructor('return process')().exit()") but in fact it will cause Node to terminate.

You may alternatively wish to consider using Patrik Simek's vm2 which offers similar functionality but claims to "run untrusted code with whitelisted Node's built-in modules. Securely!" An example from the documentation:

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

const vm = new VM({
    timeout: 1000,
    sandbox: {}
});

vm.run("process.exit()"); // throws ReferenceError: process is not defined
like image 41
cpcallen Avatar answered Nov 15 '22 08:11

cpcallen