限制 npm 依赖模块对 require(隔离)的使用

Posted

技术标签:

【中文标题】限制 npm 依赖模块对 require(隔离)的使用【英文标题】:Restricting an npm dependency module's usage of require (isolation) 【发布时间】:2016-09-07 08:26:39 【问题描述】:

有没有办法通过限制 require 的使用来 require 一个 npm 模块?

例如,一个应用程序可以提供一个系统来扩展它的一些功能,方法是提供(作为上传可能)一个满足给定合同的 npm 模块(说它导出一个类使用方法process)。该模块,如果它知道将require 的应用程序的源代码,它可能会require('db').connect().flush() 或类似的东西。

此应用程序扩展可以require 来自其主机的任何内容并对其进行修改。 npm 是否允许限制/安全方法来处理这种情况(可能通过使用进程)?

谢谢。

【问题讨论】:

【参考方案1】:

Node.js 和 npm 都不提供沙箱模块的工具。尽管对模块的实际加载方式有一点了解,但我们可以轻松实现这样的机制。

让我们看看,一个模块gets access to require

一旦 require 准备好,整个加载的源代码将被包装在一个新函数中,该函数将 require、module、exports 和所有其他公开的变量作为参数。这会为该模块创建一个新的功能范围,从而不会污染 Node.js 环境的其余部分。

其实我们可以在source code看到准确的模板:

NativeModule.wrapper = [
    '(function (exports, require, module, __filename, __dirname)  ',
    '\n);'
];

所以我们可以利用相同的方法,将上传的模块包装在 IIFE 中在需要它之前

(function (exports, require, module, __filename, __dirname) 

    // module source

(exports, undefined /* here's the trick */, module, __filename, __dirname);

现在我们可以安全地 require 封装的模块,因为它不能再访问 require 函数了。

【讨论】:

【参考方案2】:

NPM 没有提供任何东西来实现这一点,但根据您的要求,您可以通过覆盖节点的 require 语句来实现某种程度的安全性。

const MY_SECRET_TOKEN = '1234';
const rekuire = global.require;
global.require = function(nodeModule, token) 
  if (nodeModule !== 'db' || MY_SECRET_TOKEN === token) 
    return rekuire(nodeModule);
  

  throw new Error('Unauthorized attempt to access secure module "db"!); 
;

恶意模块仍然可以解决这个问题。实际上,您的重点应该是仔细审查您使用的模块,我永远不会在产品中使用上述模块。

【讨论】:

以上是关于限制 npm 依赖模块对 require(隔离)的使用的主要内容,如果未能解决你的问题,请参考以下文章

一次开发多个 npm 模块的方法(具有交叉依赖关系)

npm Guide

Commonjs

我无法让 npm 模块与 require 一起工作?

require.js ---- 基本使用

require.js ---- 基本使用