What is Sandbox
A sandbox is an environment virtual space in which set of programming instructions can be executed in isolation, without effect on the surrounding network or its applications. Sandboxes are used in both web development and cybersecurity to safely test, monitor, and experiment with software.
NodeJs Sandbox
A sandbox environment in NodeJs can be created by using the following ways:
VM2
VM2
is a NodeJs sandbox that can run untrusted code with whitelisted Node's built-in modules as well as external modules, it has various security features to prevent vulnerability os untrusted code. Following is the example of a sandbox timeout
const {NodeVM} = require('vm2');
const vm = new NodeVM({
require: {
external: true,
builtin: ['timers/promises'],
root: './'
}
});
async function test() {
const sandboxTimeoutFunc = vm.run(`
exports.executeTimeout = async (args) => {
console.log(args);
console.log("started at", Math.floor(new Date().getTime() / 1000));
const timersPromises = require('timers/promises');
await timersPromises.setTimeout(3000);
console.log("ended at", Math.floor(new Date().getTime() / 1000));
};
`);
await sandboxTimeoutFunc.executeTimeout({"foo": "bar"});
}
test();
Execute sandbox code with custom node modules or a lambda layer:
const {NodeVM} = require('vm2');
const vm = new NodeVM({
require: {
external: true,
builtin: ['timers/promises']
}
});
async function test() {
const sandboxPostReqFunc = vm.run(`
const axios = require("axios");
exports.execute = async (args) => {
console.log(args);
console.log("started at", Math.floor(new Date().getTime() / 1000));
await axios.post("https://sometestserver.com/todos", { params: { hello: "world" }});
console.log("ended at", Math.floor(new Date().getTime() / 1000));
};
`, '/opt/nodejs/node_modules'); // specify your custom path here
await sandboxPostReqFunc.execute({"foo": "bar"});
}
test();
NodeVM
The node:vm
module enables compiling and running code within V8 Virtual Machine contexts. The vm module in Node.js is available by default — no need for NPM. Once it is implemented, we can define the actual JS code we want to execute. To execute the code in the VM, we call runInThisContext.
const vm = require('node:vm');
const code = `console.log('hello from the sandbox vm')`;
vm.runInThisContext(code) // hello from the vm
executing code with node modules
const nodeVM = require('node:vm');
const timersPromises = require('timers/promises');
async function runScript(code, context = {}, options = {}) {
return new Promise((resolve, reject) => {
const { timeout = 120 * 1000, breakOnSigint = true } = options;
const script = new nodeVM.Script(`(async()=>{${code}})()`);
script.runInContext(nodeVM.createContext({
...context,
resolve,
reject,
}), {
timeout,
breakOnSigint,
});
});
}
(async () => {
const context = {
timersPromises: timersPromises,
}
const sandboxCode = `
console.log("execution started at", Math.floor(new Date().getTime() / 1000));
await timersPromises.setTimeout(3000);
console.log("execution ended at", Math.floor(new Date().getTime() / 1000));
resolve();
`;
await runScript(sandboxCode, context)
})();