There was a bug in NPM as of version 5.7.0. In short, running as a user but using NPM sudo escalation would use the identity of the user as the owner of files modified by NPM, rather than the identity of root. This would happen for any file or directory that NPM would modify, when as root, AIUI.
Relevant bug report here.
This issue has been happening ever since 5.7.0 was released a few hours ago. It seems to have completely broken my filesystem permissions and caused me to have to manually fix the permissions of critical files and folders. I believe that it is related to the commit 94227e1 which is traversing and running chown on the wrong, often critical, filesystem files and folders.
By running sudo npm under a non-root user (root users do not have the same effect), filesystem permissions are being heavily modified. For example, if I run
sudo npm --helpor
sudo npm update -g, both commands cause my filesystem to change ownership of directories such as
/boot, and other directories needed for running the system. It appears that the ownership is recursively changed to the user currently running npm.
I found that a selection of directories in
/were owned by a non-root user after running
sudo npmand many binaries in
/usr/binstopped working as their permissions were changed. People experiencing this bug will likely have to fully reinstall their system due to this update.
npm update -gas
No output, all packages up to date. Likely still causes a
chownto be run silently to
drwxr-xr-x 10 root root 129 Feb 22 03:39 /usr
Then doing a
su jared(a non-root user):
sudo npm update -gas
EPERMoutput, almost always corrupts the filesystem.
drwxr-xr-x 10 jared jared 129 Feb 22 03:39 /usr
Some significant and relevant bits of information can be extracted from this:
- A flaw in
npmbroke multiple users systems.
npmis commonly run in a “global” mode that requires
I think this is unacceptable.
We, as people who acknowledge that there are flaws in software, should not be
as trusting as we are. We shouldn’t give programs the ability to mutilate our
system and potentially make it unusable, just because we want to install
lolcat to make things show up as a nice and pretty rainbow colour (yes,
lolcat is ruby, not JS, but that’s not the point).
We shouldn’t be using software put in the hands of people that we don’t trust.
We shouldn’t be giving root permissions to programs that don’t need it. If
a program doesn’t need to be installed system-wide, it shouldn’t need to be
With an organization I work with - Hashbang, Inc. - we let users run amok on a
shared system, doing as they please. These users typically want to install some
things to make their lives easier, but I’m
lazy security-oriented, so we
needed a way to let users install software without being able to destroy the
We need a directory where users can put things that don’t need to be permanent, that shouldn’t be able to affect other users, that can be replaced if needed, and don’t need root permissions which - if taken away - can cause the system to become irreparably broken. This directory would be useful for storing their configuration files, their media, and their programs. Wait… That’s just-
$HOME - The directory built by you, for you.
Users have their own directory. They’re allowed to put whatever they want in that directory. They can store NSA secrets, massive amounts of material used for personal satisfaction, games, and other things. There’s no reason we can’t also include binaries, libraries, and configuration files in that directory.
But, NPM requires root!
Actually, while a lot of these binary package installers mostly tell you to use
sudo when installing things (with exception to Rust and Go, bless them) you
can still make them use your home directory through some simple RC changes.
I’ve set up an example below that you can copy, for Lua, Python, Ruby, and NodeJS. You can look up relevant examples for other software.
# Lua # Use `--local` when invoking the aliases to get your HOME path. alias luarocks-5.1="lua5.1 /usr/bin/luarocks" alias luarocks-5.2="lua5.2 /usr/bin/luarocks" alias luarocks-5.3="lua5.3 /usr/bin/luarocks" # Need to do 5.1 last, as it adds to LUA_PATH, which would be picked up by the # other PATH commands. eval `lua5.3 /usr/bin/luarocks --bin path` eval `lua5.2 /usr/bin/luarocks --bin path` eval `lua5.1 /usr/bin/luarocks --bin path` # Python, and a few other things # For Python's package manager `pip`, use the `--user` flag when installing. export PATH="$HOME/.local/bin:$PATH" # Ruby # Ruby automatically installs as user, but most systems don't use the # Ruby binary installation directory for loading binaries. export PATH="$HOME/.gem/bin:$PATH" # Node.js export PATH="$HOME/.npm_packages/bin:$PATH" export NODE_PATH="$HOME/.npm_packages/lib/node_modules" export NPM_CONFIG_PREFIX="$HOME/.npm_packages"
Programs that don’t need to interact with hardware can often be run as your
own user. I’ve recently moved to systemd user units for my Hashbang setup, so
I’m able to automatically start my personal nginx webserver when I first
connect, and on your systems you can use
loginctl enable-linger <user> to set
libpam-systemd to start on system startup.
I’ll provide the configuration I use for my personal webserver, as an example
of how to start nginx on system startup. You can use this for any software,
like a music player. Additionally, you can get rid of a dependency on
using systemd timers, as most cron implementations run
outside of the users’ session preventing functions like resource limiting from
EDIT-2020-08-15: Rewrite to be less snarky.