Question

When you create a new repl instance in code it automatically has access to anything in global scope. You can modify the repl context to expose some custom variables in local scope so that the repl can access them, but I don't see an easy way to eliminate access to the global scope. I wish I could just give the repl a new blank global scope.

Here is an example repl instance:

var repl = require('repl'),
    msg = "Hello world!";
repl.start('> ').context.msg = msg;

In that repl I typed out the following:

for (var key in global) {
    console.log(key);
}

Which resulted in the following list:

  • ArrayBuffer
  • Int8Array
  • Uint8Array
  • Uint8ClampedArray
  • Int16Array
  • Uint16Array
  • Int32Array
  • Uint32Array
  • Float32Array
  • Float64Array
  • DataView
  • DTRACE_NET_SERVER_CONNECTION
  • DTRACE_NET_STREAM_END
  • DTRACE_NET_SOCKET_READ
  • DTRACE_NET_SOCKET_WRITE
  • DTRACE_HTTP_SERVER_REQUEST
  • DTRACE_HTTP_SERVER_RESPONSE
  • DTRACE_HTTP_CLIENT_REQUEST
  • DTRACE_HTTP_CLIENT_RESPONSE
  • COUNTER_NET_SERVER_CONNECTION
  • COUNTER_NET_SERVER_CONNECTION_CLOSE
  • COUNTER_HTTP_SERVER_REQUEST
  • COUNTER_HTTP_SERVER_RESPONSE
  • COUNTER_HTTP_CLIENT_REQUEST
  • COUNTER_HTTP_CLIENT_RESPONSE
  • global
  • process
  • GLOBAL
  • root
  • Buffer
  • setTimeout
  • setInterval
  • clearTimeout
  • clearInterval
  • setImmediate
  • clearImmediate
  • console
  • module
  • require
  • msg
  • _
  • key

You can see that our msg variable was added in there, which is great, but there are many global variables I do not want to expose. I want to expose some of the less harmful ones, such as setTimeout, console, etc, but definitely not things like require, process, etc. Does anyone know how I might overcome this without spawning a totally new child process?

Was it helpful?

Solution

I don't know if this is the best solution but I did manage to accomplish this. The context object for the repl is the global object. It's just automatically augmented with everything from global. This means you can iterate over the properties on it and remove the ones you are not interested in.

https://gist.github.com/Chevex/7000130

// Function to determine if an array contains a specific value.
function contains(array, value) {
    for(var i = 0; i < array.length; i++) {
        if(array[i] === value) return true;
    }
    return false;
}

var repl = require('repl'),
    newRepl = repl.start('> ');

var allowedGlobals = ['ArrayBuffer', 'Int8Array', 'Uint8Array', 'Uint8ClampedArray', 'Int16Array', 'Uint16Array', 'Int32Array',
    'Uint32Array', 'Float32Array', 'Float64Array', 'DataView', 'Buffer', 'setTimeout', 'setInterval',
    'clearTimeout', 'clearInterval', 'console', '_'];

for (var key in newRepl.context) {
    if (!contains(allowedGlobals, key)) {
        delete newRepl.context[key];
    }
}

It's kind of annoying having to maintain a string array of global variables I want to allow, but at least this white-lists them. If node updates and adds something new to the global scope it won't be exposed until I explicitly add it to the list.

If you need to also white-list repl commands or eliminate the repl's access to node core modules then see this question.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top