Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

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

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

like image 637
broofa Avatar asked Sep 16 '11 15:09

broofa


People also ask

How do I run a node script?

The usual way to run a Node. js program is to run the globally available node command (once you install Node. js) and pass the name of the file you want to execute. While running the command, make sure you are in the same directory which contains the app.

What is Sandbox in node JS?

Securely sandboxing Node. js is a common requirement and has a wide range of applications. From simply allowing customers to test Javascript on your site to allowing customers to write custom code in middle layers in your application.


2 Answers

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.

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.

The untrusted code is then wrapped in a closure with strict mode (in regular JavaScript, you can use arguments.callee.caller to access data outside of your scope). Finally, a very limited global object 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.

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.

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 example seems straightforward.

like image 157
Laurent Perrin Avatar answered Sep 21 '22 08:09

Laurent Perrin


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

like image 32
Alan Mimms Avatar answered Sep 20 '22 08:09

Alan Mimms