1

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?

CatDadCode
  • 58,507
  • 61
  • 212
  • 318
  • 1
    One could `with`-shadow said variables (as well as shadowing the global scope variable). Although there are still ways around that (e.g. in a callback or a bind without a specified `this`). – user2864740 Oct 15 '13 at 23:05
  • I'm not 100% sure but I don't think the ways around it actually get around it in the repl. I tried doing `console.log(this);` from within a timeout and the object that was displayed was some custom object obviously related to setTimeout, not the global scope. I also created a function that displays `this` then created a new function using `bind` specifying `null` for `this` and all that displayed was an empty object. – CatDadCode Oct 15 '13 at 23:53

1 Answers1

1

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.

Community
  • 1
  • 1
CatDadCode
  • 58,507
  • 61
  • 212
  • 318
  • This leaves the user with access to ```fs```. They can easily destroy everything with that. – woverton Apr 08 '15 at 09:12
  • @woverton That's not what this question was about. However, you can eliminate repl's default access to core modules easily by setting `repl._builtinLibs = [];` before you start the repl. That will eliminate the `fs` module as well as the rest of the node core modules from being loaded by default. See [this question](http://stackoverflow.com/questions/19393599/how-do-i-limit-the-node-repls-access-to-internal-node-modules) for that. Keep in mind that I'm not endorsing making your repl publicly accessible. It's likely there are still edge cases, like unhandled exceptions. – CatDadCode Apr 08 '15 at 16:23