I would like to have the ability to let users submit arbitrary JavaScript code, which is then sent to a Node.JS server and safely executed before the output is sent back to
Depending on your usage, I'd suggest you also consider protecting your sandbox with a virtual environment like gVisor. You can find some info here.
Under Node.js you may create a sandboxed child process, but you also need to append the code with "use strict";
, otherwise it is possible to break the sandbox with arguments.callee.caller
.
Not sure why you need to send it to the server, because the code may also be executed in a sandboxed web-worker.
Also take a look at my Jailed library which simplifies everything just mentioned for both Node.js and web-browser, and additionally provides an opportunity to export a set of functions into the sandbox.
This answer is outdated as gf3 does not provide protection against sandbox breaking
http://gf3.github.io/sandbox/ - it uses require('child_process')
instead of require('vm')
.
One alternative would be to use http://github.com/patriksimek/vm2:
$ npm install vm2
then:
const {VM} = require('vm2');
const vm = new VM();
vm.run(`1 + 1`); // => 2
as mentioned in comments of other answers.
I don't know how secure it is, but it at least claims that it runs untrusted code securely (in its README). And I couldn't find any obvious security issues so far as solutions suggested in other answers here.
You can use sandbox support in nodejs with vm.runInContext('js code', context), sample in api documentation:
https://nodejs.org/api/vm.html#vm_vm_runinthiscontext_code_options
const util = require('util');
const vm = require('vm');
const sandbox = { globalVar: 1 };
vm.createContext(sandbox);
for (var i = 0; i < 10; ++i) {
vm.runInContext('globalVar *= 2;', sandbox);
}
console.log(util.inspect(sandbox));
// { globalVar: 1024 }
WARN: As pointed by "s4y" it seems to be flawled. Please look at the comments.