为什么npm建议不要以root用户身份运行?

60

简而言之...

首先,为什么npm建议只以非根用户身份运行?我不相信每个其他的包管理器(apt, yum, gem, pacman)都因为需要sudo而是错的。

其次,当我遵循他们的建议(以非root用户运行npm install)时,它并不能正常工作(因为非root用户没有对/usr/local/lib的权限)。那么我该怎么做呢?我不会chown -R $USER /usr/local/lib,因为这听起来对我来说是一个非常糟糕的主意。

完整描述...

我通过执行curl http://npmjs.org/install.sh | sudo sh(在他们的README里的指示)安装了npm

当我以sudo身份运行sudo npm install mongoose时,npm告诉我不要以root身份运行:

npm ERR! sudon't!
npm ERR! sudon't! Running npm as root is not recommended!
npm ERR! sudon't! Seriously, don't do this!
npm ERR! sudon't!

但是,如果我在没有使用sudo的情况下运行npm install mongoose,则会得到以下结果:

npm info it worked if it ends with ok
npm info using npm@0.2.17
npm info using node@v0.4.0-pre
npm info fetch http://registry.npmjs.org/mongoose/-/mongoose-1.0.7.tgz
npm info calculating sha1 /tmp/npm-1297199132405/1297199132406-0.7044695958029479/tmp.tgz
npm info shasum b3573930a22066fbf3ab745a79329d5eae75b8ae
npm ERR! Could not create /usr/local/lib/node/.npm/.cache/mongoose/1.0.7/package.tgz
npm ERR! Failed creating the tarball.
npm ERR! This is very rare. Perhaps the 'gzip' or 'tar' configs
npm ERR! are set improperly?
npm ERR!
npm ERR! couldn't pack /tmp/npm-1297199132405/1297199132406-0.7044695958029479/contents/package to /usr/local/lib/node/.npm/.cache/mongoose/1.0.7/package.tgz
npm ERR! Error installing mongoose@1.0.7
npm ERR! Error: EACCES, Permission denied '/usr/local/lib/node/.npm/.cache/mongoose'
npm ERR! There appear to be some permission problems
npm ERR! See the section on 'Permission Errors' at
npm ERR!   http://github.com/isaacs/npm#readme
npm ERR! This will get better in the future, I promise.
npm not ok

这告诉我不应该使用sudo,但如果我按照他们的建议操作,它就无法工作。

这导致了我之前提出的问题。


1
这是我的理解。其他的软件包管理器例如apt应该以root身份运行(https://help.ubuntu.com/community/AptGet/Howto),因为它们已经正确构建。`npm`没有完全完成他们的产品,所以`npm`本来应该能够作为root运行,但是他们还没有完成这个功能(https://github.com/isaacs/npm/issues/294)。在他们完成之前,使用sudo运行实际上是不安全的。 - Alexander Bird
3
因为写这个的家伙真的很烦人,这是我能想到的全部。 - Cole
3个回答

50

实际上,npm不再推荐不以root用户身份运行。这一变更是在你提出问题的同时进行的。2011年2月7日README的内容如下:"使用sudo安装npm非常不推荐。任何人都可以发布任何东西,并且包安装可以运行任意脚本。"稍后详细解释为:"选项4:我的天啊,不推荐!!你可以为所有事情始终使用sudo,并忽略那些告诉你这样做是疯狂的极其恶心的警告。"

参见:https://github.com/isaacs/npm/tree/7288a137f3ea7fafc9d4e7d0001a8cd044d3a22e#readme

现在,它被认为是安装npm的一种推荐方法:

简单安装 - 要用一个命令安装npm,请执行以下操作:

curl http:/ /npmjs.org/install.sh | sudo sh

参见:https://github.com/isaacs/npm/tree/99f804f43327c49ce045ae2c105995636c847145#readme

我的建议是永远不要这样做,因为基本上意味着:

  1. 找出本地DNS(或任何欺骗DNS响应或污染DNS缓存的人)所说的npmjs.org的IP地址
  2. 使用该IP(或声称是其IP的任何人)在端口80上连接不安全TCP
  • 相信你认为应该与之交流的路由器(或任何给你DHCP响应并告诉你要与之交流的人)能够将数据包传送到正确的主机
  • 可能需要通过另一层透明缓存代理
  • 相信在你和TCP连接另一端之间的所有其他网络
  • 不确定与谁连接
  • 祈求好运
  • 通过不安全的HTTP请求安装.sh脚本,而完全没有验证
  • 然后以最高权限在你的机器上运行由你正在通信的任何人返回的内容,甚至不检查它是什么。
  • 正如您所看到的,这确实是一种无论如何都会将root shell赋予您从互联网上通过不安全连接获取的任何内容。这里至少有5个不同的问题可能出现,其中任何一个都可能导致攻击者完全控制您的机器:

    1. DHCP欺骗
    2. ARP欺骗
    3. DNS缓存污染
    4. DNS响应欺骗
    5. TCP会话劫持

    还请注意,除非您将其作为没有访问您私人数据权限的不同用户运行,否则使用'sh'而不是'sudo sh'通常并不会降低风险,这种情况通常不会出现。

    如果可以使用HTTPS连接下载此类脚本,则应使用它们以便您至少可以验证与之交谈的人的身份,即使如此,我也不会在未阅读之前运行它。不幸的是,npmjs.org有自签名证书,因此在这种情况下它并没有真正帮助。

    幸运的是,npm可在具有有效SSL证书的GitHub上使用,您可以从那里使用安全连接下载它。请参见:github.com/isaacs/npm了解详情。但要确保npm本身不使用不安全的连接下载它下载的文件- npm配置中应该有一个选项。

    希望对您有所帮助。祝好运!


    2
    非常感谢你认真思考并给出的回答!这有助于我安装npm而不会遇到安全问题。然而,一旦我安装npm,我的问题的另一部分仍未得到解答。换句话说,现在我可以“安装”npm,但我该如何“使用”npm呢?我应该以root身份运行npm吗? - Alexander Bird
    1
    @Zed 不错的想法,但它们并不能真正帮助你。一旦你克隆了一个git repo并运行它的makefile,你就有可能被感染。一旦你安装了一个恶意的npm包,你也有可能被感染。此外,只要你的账户能够使用'sudo',并且你有时会用它来做事情,在被感染时不是root对攻击者的能力造成 零影响 - thejh
    @thejh,如果软件本身是恶意的,那么我的建议对你没有帮助,因为它是作者有意为之的。但在更有可能的情况下,我的建议会帮助你,即软件本身很好,但你确实没有与作者交流,而是与想要向你提供特洛伊木马版本的人交流。如果你从GitHub获取官方版本,那么我认为它的恶意程度可能会少得多。但当然,是否有root权限基本上无关紧要,因为正如我所说的,$HOME中的私人文件通常是最重要的,而且像你说的那样,还有sudo。完全同意。 - Zed
    npmjs现在使用DigiCert作为授权机构的https连接,因此您可以确信您正在与谁交流。 - SharpEdge

    22

    简单来说,由于众所周知的安全原因,Web服务器永远不应该以root身份运行,因此npm命令也是如此。

    为了重新开始,需要删除之前安装的Node.js和npm,以及这些文件/目录:

    mv ~/.npmrc       ~/.npmrc~prior
    mv ~/.npm         ~/.npm~prior
    mv ~/tmp          ~/tmp.~prior
    mv ~/.npm-init.js ~/.npm-init.js~prior
    

    解决方法:以非root用户身份(不使用sudo)安装Node.js(附带npm)。

    直接从https://nodejs.org/en/download/下载源代码。

    在Linux/OS X操作系统下,以当前用户的身份执行以下命令:

    cd node-v8.1.2  # into expanded source dir
    
    export NODE_PARENT=${HOME}/node-v8.1.2 # put this into your ~/.bashrc
    

    随意将上述导出更改为适当的位置

    ./configure   --prefix=${NODE_PARENT}
    make -j4   # for dual core ... use  -j8  for quad core CPU
    make install
    

    这将把 Node.js 和 npm 的二进制文件以及它们的模块存储库放在 $NODE_PARENT 中,$NODE_PARENT 是 $USER 拥有的目录,这样您就可以像自己一样执行后续的“npm install xxx”命令。

    要访问 node 和 npm 的二进制文件,请在您的 ~/.bashrc 中更改 PATH 环境变量:

    export PATH=${NODE_PARENT}/bin:${PATH}
    export NODE_PATH=${NODE_PARENT}/lib/node_modules
    

    然后要将软件包安装到该目录(全局),而不是当前目录(本地),始终传递-g标志(全局):

    那么要将软件包安装到该目录(全局),而不是当前目录(本地),始终传递-g标志(全局):

    npm install -g someModule
    

    注意-在任何时候,您都不应该以root/sudo的身份执行任何与npm或node相关的操作。


    1
    谢谢Scott,完全卸载后这对我帮助很大。 - Peadar

    2

    不要在root下安装NPM包的另一个原因是,这会导致你在使用node-gyp(例如:node-sass)的包时面临文件访问问题,因为它构建C++库,而这些库不在本地的node_modules文件夹中。


    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接