The npm community forum has been discontinued.
To discuss usage of npm, visit the GitHub Support Community.
Security risk associated with ownership change of a package, what's your thought on the process?
There is a security risk when there is a change in ownership of a package, and this is a problem that needs to be solved. Our security team thought about some ideas that @adam_baldwin shared in his latest article, but we want to do that with the input of maintainers and the users depending on these packages.
Even if we know that there isn’t a solution that will reduce the risk to zero, what is your opinions or ideas on the best way to mitigate this issue?
Well, to start, we need better tools for determining who the maintainers for a particular dependency tree are, and a way to be notified when that list changes. Right now, the state of the art on this is “go to npmjs.org, look up each package (including all dependencies) individually, and read the list of maintainers”. That’s untenable for most people and even most organizations.
Instead, there needs to be an easy way to see the entire list of maintainers for a given package, including the maintainers of every package in its dependency tree. I’d start by listing that information on npmjs.org, and providing a way to fetch that list through the CLI.
For notifications of ownership changes, I think a good first step would be to make that information more visible by displaying it every time npm updates a package. Something like "
<person> as a maintainer" printing in the command line right next to the updated package version number would make changes like that more apparent and make it much less likely for a suspicious change in ownership to go undetected.
Once that system is in place, you could also add an optional setting or CLI flag to make such changes require manual approval before the package will actually install. I would not recommend trying to enforce this through Semver as Adam proposed. A change in maintainers is not necessarily a breaking change to the package itself. Furthermore, I suspect such restrictions would lead to insecure practices like maintainers sharing their account password to get around the restriction.
That’s a really interesting perspective on forcing a breaking change causing too much friction leading to insecure practices, thanks for sharing it. We know that users will circumvent controls that cause too much friction.
Providing users with the right information at the right time to make an informed decision seems to be a nice way to approach this. I do worry about the chore that puts on the developer and am interested in finding ways to make this an easier process.
Yes, it’s certainly a difficult problem. Ultimately it comes down to trust. Can you trust the new package maintainer just as much as you trusted the old maintainer? Ideally the old maintainer would vet new maintainers thoroughly before granting them publish access, but as we’ve seen from past examples that doesn’t always happen.
I understand the desire not to burden developers with additional tasks, but ultimately I do think the person installing the package needs to bear at least some level of responsibility for who they’re trusting when they take that action. Before they can do that though, they need to at least know who they’re trusting in the first place.
One alternate (or additional?) approach you could take would be to reduce the need for trust by vetting the code instead of the maintainers. (Arguably, vetting code is a lot easier than vetting people.) Obviously NPM doesn’t have the resources to manually review every package that gets published, but you could probably design some sort of system for facilitating the review of packages by third parties. Perhaps a way for users to review the source code of a published package on the website and add their personal stamp of approval? Then even if a developer doesn’t trust a particular maintainer, they could still install packages published by that maintainer as long as those packages were reviewed by someone the developer does trust. (Such as another developer on their team, or the original package maintainer reviewing the code published by a new maintainer they granted publish rights to.)
Sounds like a lot of work, sure. But again, this is a rather difficult problem to solve. Just throwing some ideas out there.
I really like the suggestions around showing the right information to the users at the right time. I also agree that we need to facilitate this process for the developers, but at the same time that there are some levels of ownership that should be taken. How often people just install packages without really checking if it is what it says it is? Most of the time I guess…
This doesn’t have anything to do with package ownership. There’s a lot of misdirected frustration here.
An audit log of maintainers added/removed will eventually be a bunch of noise. I can’t envision many package consumers spending the time and resources to “vet” new maintainers, whatever that looks like.
99% of the time, when a package changes hands, it’s a win. That’s how open source works.
At the registry level, if it’s an open registry, people will publish malicious code. Only an actively curated registry would be an effective way to reduce the potential for a registry to be used as an attack vector. I’ll leave the economics of that up to the reader.
At the consumer level, use a lockfile and inspect any updated code. Likewise, if that sounds tedious, pay some company or hire people to curate a registry.
If there’s anything npm could do to enable the above, try these:
- providing “diff” output when any packages are updated could be helpful for those determined to check. not my idea
- wizard-like interface when updating (similar to what @zkat demoed recently) which walks thru all changes coming down the pipe
- A registry which is also n months “behind” the open public registry would be useful for the risk-averse. The assumption being that most people wouldn’t use it, and they’d get bit by issues, but those will get fixed before reaching the delayed registry. also not my idea
- my dumb idea: extra big disclaimer statements on the registry site and upon
npm installthat reminds users the registry is not actively curated and that they assume the risk for installing and running any unknown code.
I think that forcing a semver-major change when adding or removing maintainers would cause extreme friction and a lot of semver-major bumps.
One issue with the idea of using semver to track owner/maintainer changes is that most people have no way of knowing if a new maintainer or owner is trustworthy or not. In the
event-stream example, prior to the code being added there was no reason to not trust the new owner, especially considering the first thing he did was add a legitimate feature, and there is an infinite amount of time available between when someone gets maintainer/ownership of a package and when they can introduce malicious code. I can quickly see people simply accepting breaking semver changes due to owner/maintainer change since they aren’t going to go and research the new people. So it will add a lot of friction without actually solving any problems, unless the malicious code was added fairly immediately, which is unlikely to happen if an attacker knows this process is in place.
I think we can all agree that packages coming from a new / unknown maintaner should not be automatically trusted.
But looking using semver to control the trust seems like a bad solution for a few reasons -
- Sure someone will need to manually approve the upgrade but does he really know if it’s a different maintainer and not just a new major ? some packages get a new major ver quite often.
Using semver hides the actual issue.
- Most new maintainers will be legit devs helping the project. what if they find security issues and other bug fixes that need to go to an older versions ? they can’t touch those versions and even if they are not adding any breaking changes most people wont upgrade major deps in old code so you’ll end unable to fix security issues in those modules
I think Ajedi suggestion makes since. And I would add that by default it should require manual interaction to update direct dependence. the cli can than offer the options to automatically install everything (ignoring this fix) or even halting on nested dependency ownership change (if you really wanna make sure your chain is intact)
Proposal: Maintenance Trust Rating
- I can’t remember the names of the maintainers of the thousands of packages that I use
- I don’t want to give out my name or email to everyone who installs my packages, I am not tech support.
- Even the maintainers of the current packages that I am already using may be untrustworthy, what do I know?
- The entity that knows the most about the maintainers of the packages is npm.
I want a quick summary per package, of how known or unknown a maintainer the package has, or if the maintanance has changed. More importantly, I want to know if the packages that I am currently using already, require keeping more of an eye on! I also want to know if something changes drastically in the future.
- For each maintainer, calculate the number of packages that they publish.
- Give each maintainer a trust rating from 0 to 10 based on how many packages they maintain and how long the account has existed for.
- Now give each package a “Maintainer Trust Level” that for a start, simply averages the rank of each maintainer!
Maintainer trust level 0 + Maintainer trust level 0 / 2 = Package Maintainer Trust Level: 0
Maintainer trust level 9 + maintainer trust level 0 + maintainer trust level 0 / 3 = Package Maintainer Trust Level: 3
Maintenance trust level 9 / 1 = Package Maintainer Trust Level: 9
I am using package X, which is maintained by a well-known single maintainer who maintains 30 other npm packages and he has had that account for 4 years. That package maintainer’s trust level is 9, and thus the package’s Maintainer Trust Level is 9. He adds a second maintainer because he doesn’t have time to maintain the package on his own any more. That maintainer has no other packages, and an account that has only existed for 30 days. Their trust level is 0. The package’s Maintainer Trust Level drops from a 9 to a 4.5 for all subsequent releases! Warn me of this drop when I go to upgrade!
I am considering a new package Z because it has the cool features that I want. Who published it? Williams Norman. Not a name that I recognize. Do I trust him? no idea. Oh, wait, this is his only package and he has only had an npm account for 5 days. So this package has a trust rating of a big fat 0. I should proceed with caution if not look elsewhere for my cool feature.
I was just brought in on an application that is a high security banking app. I need to audit which packages are being used, where do I start? I run an npm command to get the maintenance trust levels of ALL of my packages and start scrutinizing the packages with 0’s first, then the 1’s, etc.
In summary: Put a quickly visualize-able abstraction around a trust level rating based on the information you already have. Expose the rating level. Iterate the factors that go into the rating.
The main issue with offering automatic validation of maintainers is that it’s easly exploitable.
If you only look at the number of packages & account creation time a persistent attacker can easily create hundreds of fake packages and create throwaway users just so they’ll sit until the time they are old enough to be used in an attack.
Also this information is kinda available for you today. You can see on npm all the other packages an individual published and very easily tell if it’s relatively new account or an old one.
On the other side it will prevent from new devs and individuals who might only have a couple of modules they publish to have a good rating and thus prevent them from having a fair go with publishing their packages (It’s hard as is to find on npm anything other than the most popular packages).
I’m all for validating maintainers if npm want to have a go at it. but it has to be actual have a chat maybe see some I.D to disincentive malicious actors (publicly the information that should be available is if the account has been vetted or not).
I’m not sure if NPM has the resources to start vetting devs, but I think if they do it might be better to vet code auditors instead. and then let vetted auditors to audit version of packages they use.
That way we split the trust between the package owners and whoever volunteered their time to audit they’re code (hopefully for highly depend upon packages there will be a number of independent auditors).
one easy piece of low hanging fruit would be to let us set a boolean flag that checks our
package-lock and disallows an install if the owner changed
it’s not a long term solution but it would allow concerned people an easy first-step mitigation with no need to change surrounding infrastructure
trustNewMaintainers: false or something like that in
package.json should be enough
granted it’ll cause minor issues when, for example, a library switches from its original author to an org, like when d3 switched from mbostock to d3 org
but honestly that doesn’t seem like a big deal to me. “install d3 v4.” “no, it’s not mbostock anymore. uninstall and reinstall if you’re sure.”
would work for me.