How do I limit the node repl's access to internal node modules?

半城伤御伤魂 提交于 2020-01-06 08:09:31

问题


In a previous question I figured out how to eliminate unwanted global variables from the repl context. However, I figured out that the repl automatically has access to ALL internal node modules without the use of require. I have no idea how to disable this. I even tried overriding the module variables in the repl itself and it doesn't work.

> fs = "test";
> fs

It still displays fs original value. This is very unfortunate because I'm trying to expose a public repl but it gives them access to the entire server.

Any ideas?


回答1:


As you said, the REPL has access to core modules.

(however, after checking, I am able to override them with node 0.10.20, so there should be a solution)

> fs
> { Stats: [Function], …
> fs = 'hello';
> fs
'hello'

A better way would be to just override repl._builtinLibs before creating a repl instance.

var repl = require('repl');
repl._builtinLibs = [];
repl.start('> ');

Also, it's fairly trivial to white-list repl commands if you don't want to expose commands like .save or .load.

var allowedReplCmds = ['.break', '.clear', '.help'];

var newRepl = repl.start('> ');
for (var key in newRepl.commands)
    if (!allowedReplCmds.contains(key))
        delete replInstance.commands[key];

Note: Arrays don't normally have a contains method so I added one.

Array.prototype.contains = function(v) {
    for(var i = 0; i < this.length; i++) {
        if(this[i] === v) return true;
    }
    return false;
};

If you want to remove variables from the repl instance's global scope see this question.


Please note that it is very unsafe to expose a REPL to the public.

You can easily crash the whole server

> setTimeout(function () { throw 'bye bye!'; }, 0);

Errors that happen in async callbacks are not caught by the REPL and bring down the node.js instance.

You can block the server

> while(true) {};

Your best bet would be to code your own REPL in a separate process with child_process, readline and vm. Here's a starting point:

The master:

// master.js
var fork = require('child_process').fork;

// functions exposed to the repl
var replApi = {
  hello: function () {
    return 'world!';
  },

  unknown: function () {
    return 'unknown';
  }
};

function forkRepl() {
  var repl = fork('./child_repl');

  repl.on('message', function (command) {
    var fun = replApi[command] || replApi.unknown;
     repl.send(fun());
  });

  // restart the repl if it dies
  repl.on('exit', forkRepl);
}

forkRepl();

and the separate process for the repl:

// child_repl.js
var readline = require('readline'),
    vm = require('vm');

var context = vm.createContext({
  hello: function () {
    process.send('hello');
  }
});

var rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

rl.on('line', function (line) {
  vm.runInContext(line, context, 'repl.vm');
});

process.on('message', function (message) {
  console.log('master:', message);
});

rl.prompt();


来源:https://stackoverflow.com/questions/19393599/how-do-i-limit-the-node-repls-access-to-internal-node-modules

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!