What does unsafe-perm in npm actually do?
I’ve routinely been directed to what feels like a magic fix to issues when installing items over NPM. The issue that I’ve most recently encountered occurs in two different OS’s; Windows and Elementary. When attempting to install Sindre Sorhus’ Pure ZSH theme both in Ubuntu WSL and Elementary Loki, I have issues with not having permissions.
The solution seems to be almost the same in both cases.
1 |
npm config set unsafe-perm true |
What exactly is this doing? Is it ‘unsafe’?
Let’s start with a search. So there is a config setting allowed in the package.json
that actually can set this per package. But wait, it’s always true unless using root. I never run as root
, or with sudo
privileges unless I am forced to. Let’s take a look through the source code
Set to true to suppress the UID/GID switching when running package scripts. If set explicitly to false, then installing as a non-root user will fail.
If npm was invoked with root privileges, then it will change the uid to the user account or uid specified by the user config, which defaults to nobody. Set the unsafe-perm flag to run scripts with root privileges.
1 2 3 4 5 6 7 8 9 |
function loadUid(cb) { // if we're not in unsafe-perm mode, then figure out who // to run stuff as. Do this first, to support `npm update npm -g` if (!this.get('unsafe-perm')) { getUid(this.get('user'), this.get('group'), cb); } else { process.nextTick(cb); } } |
In other words, if we set unsafe-perm
to always true, we will stop getting the user and the group the command was ran as and we will over-load the defaults.
1 2 3 4 5 |
'unsafe-perm': process.platform === 'win32' || process.platform === 'cygwin' || !(process.getuid && process.setuid && process.getgid && process.setgid) || process.getuid() !== 0, |
It’s starting to make a bit more sense. This issue that I’m facing is that the permissions my current user has are unable to create the symlinks that are being asked by the program. By setting unsafe-perm
to true
will force NPM
to attempt to always run within the context of the running script.
I suppose that this isn’t ‘unsafe’ but it does force the package installer to never drop into user and group switching when installing apps. It’s possible then you may end up having the code run as ‘root’ when installing (which could then be considered ‘unsafe’);
This goes all the way back to February 7th, 2011!
Initially this would cause the app to either Error out when false
or to toggle the user and group.
But finally, we reach the reasoning for this code (and still it’s not what many may expect).
You can’t please everyone.
Don’t try to be secure if it’ll fail.
If someone really wants to encourage this all the time, then they can do
npm config set unsafe-perm false
explicitly.In the npm 1.0 future, it will probably require sudo for global
installing no matter what, and use this behavior for local installing.
Since so many people have npm installing in their home dir, requiring
sudo is causing more trouble than it’s worth.
Boom
This was added to help installing files into ‘safe’ locations without sudo
.
So I think that I may have the answer?
Use this sparingly; probably bad to set globally for all running scripts. If the user is running as
root
it may cause the app to force changes that could extend beyond what a running script should have. Never run asroot
and it will betrue
by default. Usesudo
otherwise. It’s not a magic bullet.