10

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?

Greg
  • 819
  • 1
  • 8
  • 21

1 Answers1

20

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.

Greg
  • 819
  • 1
  • 8
  • 21