Join GitHub today
GitHub is home to over 36 million developers working together to host and review code, manage projects, and build software together.Sign up
Safe sudo behavior #294
The problem with running npm (or, for that matter, most package managers) as root is that the package manager trusts the packages. In order to make sudo safe at all (and, in fact safer than running as a non-root user), we need to make that not the case.
When running as root, do the following.
Get the "user" config, which defaults to "nobody".
Before running any lifecycle scripts, recursively chown the package folder to the user config. Run the script with the powerless uid. Chown back after running.
At the end, recursively chown the package folder to the original owner.
If done properly, the running scripts will only have access to their package folder, even though npm itself is running with root privileges.
The opposite problem is that, as with running with administrative privileges at all times, any attacker that gains control of a process with the privileges of the user can then alter installed packages. I don't have a proposed solution, but user-level access control is broadly known to not adequately solve either of these problems.
Depends on your definition of "adequate". I'm not looking for 100% provably-safe security, and I don't believe such a thing exists. Unless you only ever run code that you wrote, on a machine with no network access. But since npm is a program you didn't write, used to install other programs you didn't write, having fetched them over a network from a computer you don't own, 100% provably safe is out the window by design.
The goal is to prevent two things:
Having user-level access control is certainly a lot better than running arbitrary scripts with the permission level of the user or worse yet, as root. While there will always be vectors, this would cut down a significant one, and as the package manager, I think npm has a responsibility to make bad behavior as difficult as is reasonable.
Perhaps you are expanding the scope of npm too far? Should npm even be aware sudo exists? sudo is not installed by default on some distros.
For example, regarding installation of npm itself, the README provides many procedures for installing npm. However, making npm installable by the port/package systems of the major OS distros would likely be less fragile and more useful. The official port/package systems of the distros have their own protocols for dealing with port/package security.
If npm was available in major distro port/package systems, the mechanism for installing npm at the machine level would be clear and the issues of root access pertaining to the installation of npm itself would be moot as that is the problem domain of the distro port/package systems. This leaves the mechanism for installing npm packages using npm and what access levels npm should have when unpacking files and executing npm package scripts.
Regarding unpacking files, in most, if not hopefully all cases, the developer does not develop as root and the app does not run in production as root. Therefore, strictly in terms of where files get unpacked, local user installation of packages is adequate for either case. npm could simply assume a user .npmrc of:
root = $HOME/.node_libraries
If a system administrator really wants to install npm packages at the machine level, npm could assume a different, OS-specific .npmrc if the user is root. For example, this could be the effective .npmrc on FreeBSD if the user is root:
The Unix security model is very clear - processes run with the access levels of the user that executed the process. It is the user's responsibility to determine whether to trust a process, and any scripts it may download and run, before executing the process. A process can be invoked with sudo, but it should not invoke sudo.
In npm's case, the chief concern regards execution of a packages's installation scripts. A package or new package version can be added to the npm repository at any time and immediately be installed by end users without any review protocol. It may be useful to consider whether npm should even support installation scripts or at least whether it should execute them directly.
Regarding different default configs based on uid=0:
No. Strong and forceful no. Been there, done that, it's what's wrong with rubygems, and it's a mistake that I refuse to make again.
It also does not allow running with less privileges unless it is started as root.
Regarding distros that don't have sudo:
Point taken. Not sure the best workaround there. I think that sudo is common enough to be a thing that could be attempted, and then if it fails, well, it was going to fail without root access anyhow, so either put npm in insecure mode, or log in as root, or whatever.
Regarding putting npm in the "major distros":
Don't care very much about that issue at this point. Most attempts to put npm in a centrally managed opinionated distribution have resulted in an outdated and broken npm at best, and a very subtly and annoying npm at worst. Qv: debian, homebrew.
npm will be feature complete in 2011. It will be "done" (sliced and stable) probably by the end of 2012. At that time, I'll start looking at pushing adoption by other package managers, and actually care about how well that works.
Until then, that's broken, and I'm ok with it. Other fish to fry.
Regarding package installation scripts, review committees, etc.
Never. Never ever not even a little ever forever. npm will remain anarchic, free, and monitored only by a mostly hands-off dictator who is answerable to no one, forever.
I believe that this is not just the best way for software to be deployed, but also the optimal way for humans to interact with one another. The system's job is to prevent harm by default. npm currently does not do this adequately, and it's an important feature to get right. In fact, it's better to just have lots of huge warnings about it being broken, rather than pretend it's not broken when it's less than perfect. The dictator's job is to step in when the system is inadequate, or when there are annoying/confusing issues that need a human's touch. I've been filling that role with registry.npmjs.org.
If you (or anyone else) want to create a managed reviewed registry of "approved" npm packages, then you may set up your little island in that manner. I will tell you how to do it, and allow you to port all of the code in my registry if you would like. In fact, I couldn't stop you if I wanted to. It's anarchy. I can control my little dictatorship, but I can't stop you from leaving it.
But, as long as I run registry.npmjs.org, and develop npm itself, I will do it in this fashion. If everyone decides that sucks, then I'll be alone in my little island with my toy package manager, which would not be terrible.
Regarding the Unix philosophy and starting scripts:
I think that's a fine point, and certainly that is pretty much how npm runs today. However, as I stated before, the system should have some checks in place to prevent the worst and most harmful abuses.
I think most of the time it's accidents that we need to watch out for more than malicious intent. Something may be harmless on the developer's machine, but then have some awful effect elsewhere. Packagers by necessity deal in action-at-a-distance, so it's important to be a little extra careful.