One of Node.js’ core strengths is the community’s trust in npm’s registry. As it’s grown, the registry has filled with packages that are more and more interconnected.
A byproduct of being so interdependent is that a single actor can wreak significant havoc across the ecosystem. If a publisher unpublishes a package that others depend upon, this breaks every downstream project that depends upon it, possibly thousands of projects.
Last Tuesday’s events revealed that this danger isn’t just hypothetical, and it’s one for which we already should have been prepared. It’s our mission to help the community succeed, and by failing to protect the community, we didn’t uphold that mission.
This week, we’ve seen a lot of discussion about why
unpublish exists at all. Similar discussions happen within npm, Inc. There are important and legitmate reasons for the feature, so we have no intention of removing it, but now we’re significantly changing how
unpublish behaves and the policies that surround it.
These changes, which incorporate helpful feedback from a lot of community members, are intended to ensure that events like Tuesday’s don’t happen again.
Our new policy
Going forward, if you try to unpublish a given
If the version is less than 24 hours old, you can unpublish it. The package will be completely removed from the registry. No new packages can be published using the same name and version.
If the version is older than 24 hours, then the unpublish will fail, with a message to contact email@example.com .
If you contact support, they will check to see if removing that version of your package would break any other installs. If so, we will not remove it. You’ll either have to transfer ownership of the package or reach out to the owners of dependent packages to change their dependency.
If every version of a package is removed, it will be replaced with a security placeholder package , so that the formerly used name will not be susceptible to malicious squatting.
If another member of the community wishes to publish a package with the same name as a security placeholder, they’ll need to contact
firstname.lastname@example.org. npm will determine whether to grant this request. (Generally, we will.)
This can be a bit difficult to understand in the abstract. Let’s walk through some examples.
Brenna is a maintainer of a popular package named “supertools”. Supertools has 3 published versions:
0.3.1. Many packages depend on all the versions of supertools, and, across all versions, supertools gets around 2 million downloads a month.
Brenna does a huge refactor and publishes
1.0.0. An hour later, she realizes that there is a huge vulnerability in the project and needs to unpublish. Version
1.0.0is less than 24 hours old. Brenna is able to unpublish version
Embarrassed, Brenna wants to unpublish the whole package. However, because the other versions of supertools are older than 24 hours Brenna has to contact email@example.com to continue to unpublish. After discussing the matter, Brenna opts instead to transfer ownership of the package to Sarah.
Supreet is the maintainer of a package named “fab-framework-plugin”, which has 2 published versions:
1.0.0. fab-framework-plugin gets around 5,000 downloads monthly across both versions, but most packages depend on it via
Supreet realizes that there are several serious bugs in
1.0.0and would like to completely unpublish the version. He attempts to unpublish and is prompted to talk to firstname.lastname@example.org because the
1.0.0version of his package is older than 24 hours. Instead, Supreet publishes a new version with bug fixes,
Because all dependents are satisfied by
1.0.1, support agrees to grant Supreet’s request to delete
Tef works for Super Private Company, which has several private packages it use to implement static analysis on Node.js packages.
Working late one night, Tef accidentally publicly publishes a private package called “@super-private-company/secrets”. Immediately noting his mistake, Tef unpublishes secrets. Because secrets was only up for a few minutes — well within the 24 window for unrestricted unpublishes — Tef is able to successfully unpublish.
Because Tef is a responsible developer aware of security best-practices, Tef realizes that the contents of
secretshave been effectively disclosed, and spends the rest of the evening resetting passwords and apologizing to his coworkers.
Charlotte is the maintainer of a package called “superfoo”. superfoo is a framework on which no packages depend. However, the consultancy Cool Kids Club has been using it to develop their applications for years. These applications are private, and not published to the registry, so they don’t count as packages that depend on superfoo.
Charlotte burns out on open source and decides to unpublish all of their packages, including superfoo. Even though there are no published dependents on superfoo, superfoo is older than 24 hours, and therefore Charlotte must contact email@example.com to unpublish it.
After Charlotte contacts support, insisting on the removal of superfoo, npm deprecates superfoo with a message that it is no longer supported. Whenever it is installed, a notice is displayed to the installer.
Cool Kids Club sees this notice and republishes superfoo as “coolfoo”. Cool Kids Club software now depends on “coolfoo” and therefore does not break.
Changes to come
This policy is a first step towards balancing the rights of individual publishers with npm’s responsibility to maintain the social cohesion of the open source community.
The policy still relies on human beings making human decisions with their human brains. It’s a fairly clear policy, but there is “meat in the machine”, and that means it will eventually reach scaling problems as our community continues to grow.
In the future, we may extend this policy (including both the human and automated portions) to take into account such metrics as download activity, dependency checking, and other measures of how essential a package is to the community.
In balancing individual and community needs, we’re extremely cognizant that developers feel a sense of ownership over their code. Being able to remove it is a part of that ownership.
However, npm exists to facilitate a productive community. That means we must balance individual ownership with collective benefit.
That tension is at the very core of open source. No package ecosystem can survive without the ability to share and distribute code. That’s why, when you publish a package to the registry, you agree to our Terms of Service . The key lines are:
Your Content belongs to you. You decide whether and how to license it. But at a minimum, you license npm to provide Your Content to users of npm Services when you share Your Content. That special license allows npm to copy, publish, and analyze Your Content, and to share its analyses with others. npm may run computer code in Your Content to analyze it, but npm’s special license alone does not give npm the right to run code for its functionality in npm products or services.
When Your Content is removed from the Website or the Public Registry, whether by you or npm, npm’s special license ends when the last copy disappears from npm’s backups, caches, and other systems. Other licenses, such as open source licenses, may continue after Your Content is removed. Those licenses may give others, or npm itself, the right to share Your Content with npm Services again.
These lines are the result of a clarification that we asked our lawyer to make for the purposes of making this policy as understandable as possible. You can see that in this PR .
We don’t try to hide our policies; in fact, we encourage you to review their full list of changes and updates, linked from every policy page .
We acknowledge that there are cases where you are justified in wanting to remove your code, and also that removing packages can cause harm to other users. That’s exactly why we are working so hard on this issue.
This new policy is just the first of many steps we’ll be taking. We’ll be depending on you to help us consider edge cases, make tough choices, and continue building a robust ecosystem where we can all build amazing things.
You probably have questions about this policy change, and maybe you have a perspective you’d like to share, too.
We appreciate your feedback, even when we can’t respond to all of it. Your participation in this ecosystem is the core of its greatness. Please keep commenting and contributing: you are an important part of this community!
Please post comments and questions here . We’ve moved to a Github issue for improved moderation.