When I ask software developers what their biggest security concerns are, I typically hear something about malicious code in their npm packages. The average npm package has over 2000 dependencies, so the worry over malware makes a lot of sense.
The npm security team certainly shares this concern, but our job is to also look beyond the malware itself and analyze the situation that enabled it to do malicious things. These situations are varied, from mistakes like accidentally publishing a token to someone failing to take advantage of security tooling like two-factor authentication. As any security professional will tell you, human error is what transforms malware from inert code into something affecting tens, hundreds, or thousands of users.
We’ve had a few situations recently which illustrate that people are a layer beneath the code and the actions of maintainers have a direct impact on the security of the ecosystem. Specifically event-stream and koa-router.
In the case of `event-stream`, package maintainership was turned over to another person and that person acted in bad faith.
With `koa-router`, the package maintainer first offered the module for sale to support their work. npm support reached out to the original maintainer to let them know that this behavior was against our ToS, but in the end the package was transferred to a new maintainer. No malicious code has been published to date to our knowledge.
In one case we had a security incident because of a maintainer transfer and in the other we have a security risk with the potential for malicious behavior to occur.
While we’ve heard many ideas about how these issues could be fixed we need to be clear that there is no one solution that is going to reduce the risk of using these packages to zero.
One idea we’ve been considering is to use semver as a contract. Semver is a way for developers to communicate to their users how impactful a change is. It allows maintainers to disclose whether a version contains something breaking or just a simple bug fix, helping anyone using that package to act accordingly. We’ve discussed making maintainership changes a required breaking change, meaning we would lock previous version ranges from being changed and only allow for a new version to be published if the major version is incremented.
One issue with this is defining when package owner transfers happen. Is it when a new maintainer is added? That could be a real burden for some projects, but it might result in fewer maintainers which reduces some of the attackable surface area of a package and upstream dependents.
The burden flows downhill in this situation too. Tools have to present the updates as breaking changes when really they might be a patch release for a security fix.
Because we know that there is no easy solution to this, we want to make sure we gather as much info as possible and really understand how these changes will affect everyone who uses npm.
We’re going to work with the community to fix this issue.
This is a problem that needs to be solved with input from maintainers and the community that depends on these packages. As we continue to augment our enterprise offerings, we want to make sure the community is given the proper context and tooling to greatly reduce security risks.
If you have opinions or ideas on the best way to mitigate this issue, we want to hear them. Head over to npm.community and let us know what kinds of changes you’d like to see made.