In generally no matter what you will finally use, I would launch an evaluation process where you drop all privilege and only communicated with it using unix domain socket. And send the code you want to evaluate to it.
Launch it as root and open the unix domain socket and then drop the privilege to nobody.
process.setgid('nobody');
process.setuid('nobody');
One thing that you should avoid is to do something like this:
const root = global = {};
const require = function() {
console.log('tryed to call require', arguments);
}
eval("require('fs')");
This might work on the first look, but e.g. with ES6 there was the import
keyword introduces, so even if you overwrite require
you could still use import
to load module.
Also the methods mentioned in Safely sandbox and execute user submitted JavaScript? like vm.runInContext('globalVar *= 2;', sandbox);
would not help. But the referenced sandcastle, might be something you could look at, but even if you use a sandboxing library I would still suggest to run it in an isolated unprivileged process.
Like James suggested in the answer you should go the way that whitelist certain features instead of backlisting harmful ones.