NodeJS VM2 proper way to access console when set to 'redirect'

2.1k Views Asked by At

I'm using the VM2 package to run user code. I'm trying to intercept console output and have set the NodeVM object's console property to 'redirect':

    // Create a new sandbox VM for this request
    const vm = new NodeVM( {
        console: 'redirect',
        timeout: 30000,
        sandbox: { request, state, response },
        require: {
            external: true
        }
    });

According to the documentation that redirects console output to 'events'. I'm new to NodeJS, how do I hook into those events to capture the console.log messages executed inside the Sandbox?

1

There are 1 best solutions below

0
On BEST ANSWER

After digging through the source code, I found this file where the event emit is occuring:

sandbox.js

if (vm.options.console === 'inherit') {
    global.console = Contextify.readonly(host.console);
} else if (vm.options.console === 'redirect') {
    global.console = {
        log(...args) {
            vm.emit('console.log', ...Decontextify.arguments(args));
            return null;
        },
        info(...args) {
            vm.emit('console.info', ...Decontextify.arguments(args));
            return null;
        },
        warn(...args) {
            vm.emit('console.warn', ...Decontextify.arguments(args));
            return null;
        },
        error(...args) {
            vm.emit('console.error', ...Decontextify.arguments(args));
            return null;
        },
        dir(...args) {
            vm.emit('console.dir', ...Decontextify.arguments(args));
            return null;
        },
        time: () => {},
        timeEnd: () => {},
        trace(...args) {
            vm.emit('console.trace', ...Decontextify.arguments(args));
            return null;
        }
    };
}

All you need to do to listen to these events is to bind an event listener on the vm you've created:

// Create a new sandbox VM for this request
    const vm = new NodeVM( {
        console: 'redirect',
        require: {
            external: ['request']
        }
    });

    vm.on('console.log', (data) => {
        console.log(`VM stdout: ${data}`);
      });

Likewise, you can bind to console.log, console.info, console.warn, console.error, console.dir, and console.trace. Hopefully this will save someone else some time.