The Short Version
npm, the default package manager for Node.js, has officially launched staged publishing. The idea is simple: before a new version of a package is available to anyone, a human maintainer has to look at it and say yes. That extra step sits between upload and public release, and it's designed to stop attackers from sneaking malicious code into packages through compromised CI pipelines.
If you've ever published an npm package, you know the drill: run npm publish, and it's live. No waiting, no review. That convenience is also a weakness. If an attacker gets a hold of your CI credentials or your npm token, they can push whatever they want. Staged publishing changes that equation.
How Staged Publishing Works
The new workflow is built around a set of subcommands. Instead of just running npm publish, you now have the option to stage your release first.
- npm stage publish — submits the version to a staging queue
- npm stage list — shows what's waiting for approval
- npm stage view <stage-id> — lets you inspect the tarball
- npm stage approve <stage-id> — promotes it to the registry, but only after a 2FA prompt
- npm stage reject <stage-id> — discards it
The prebuilt tarball goes into a queue that's visible both on npmjs.com and in the CLI. The maintainer then has to approve it with two-factor authentication. The staging step itself doesn't require 2FA, which is a deliberate choice. It means non-interactive CI pipelines can still push to the stage queue without any extra friction. The identity check happens at the approval gate, not at submission.
There are a few technical requirements. You need npm CLI version 11.15.0 or later, Node 22.14.0 or above, and the package must already exist in the registry. So you can't use staged publishing for a brand-new package that's never been published before.
Why This Matters for Import/Export
If you're managing an npm package, you're in the import/export business, whether you think of it that way or not. You're exporting your code to the world, and you're importing dependencies from other people's packages. Both directions carry risk. Staged publishing is an export control for your own work, and it's a defense against bad imports if you're on the consuming side.
The supply chain attacks that prompted this feature were nasty. There was the Shai-Hulud worm, which hit npm packages in a way that made people sit up and take notice. Then npm deprecated traditional tokens, pushing everyone toward more secure authentication. Security researcher Adnan Khan put it bluntly on X: every developer publishing to npm should enable this feature now.
What the Community Is Saying
Not everyone is convinced. Hacker News user weinzierl called staged publishing a band-aid, saying it might actually undermine long-term efforts to build more secure infrastructure. Another user shot back that it's not a band-aid at all, arguing it's a major improvement over the status quo, specifically because it closes a class of attacks that target CI environments.
There's also the adoption question. A user named turkeyboi pointed out that the feature only helps if maintainers actually use it. Someone else suggested npm should force it on by default. On Reddit, a commenter said the approach only slows down the spread of malicious packages; it doesn't fix the root cause of supply chain vulnerabilities.
Pairing with Trusted Publishing
One of the more interesting angles is how this works with GitHub's trusted publishing. GitHub recommends combining staged publishing with OIDC-based trusted publishing. The idea is to configure your CI to only allow staged releases. That way, even if an attacker compromises your pipeline, they can't do a direct npm publish. They'd have to get past the 2FA approval step, which is a much higher bar.
If you're already using trusted publishing, the migration path is straightforward. You can reuse your existing configuration to move your packages over. Then you update your CI to the new CLI version and swap out the publish command. The CLI reference docs note that flags like --tag and --provenance behave exactly the same as they do with npm publish, so the learning curve is minimal.
New Flags and Defaults
The update also brings a few new flags. Alongside the existing --allow-git, npm now has --allow-file, --allow-remote, and --allow-directory. These can be set to all or none, and you can configure them in .npmrc or package.json. In npm v12, the default for --allow-git will change to none, which is a significant shift. It's a tightening of the screws, making it harder for scripts to do unexpected things during installation.
Competitors Are Following Suit
npm isn't the only one moving in this direction. pnpm 11.3 added pnpm stage with the same subcommands. Yarn has its own equivalent, and release-it supports a "stage": true option. On top of that, pnpm is also delaying installation of newly published versions by default, as an extra layer of protection against malicious packages that get pulled in right after release.
This is a good sign. It means the ecosystem is treating supply chain security as a shared problem, not a competitive differentiator. When the major package managers all adopt similar safeguards, the overall security posture improves for everyone.
What's Next
GitHub has published a roadmap. They plan to make fine-grained access tokens default to staged-only, which would effectively bypass 2FA for those tokens. In v12, they're adding an allowScripts field that will make install scripts non-executable by default. That's a big deal because install scripts have been a common vector for malicious code.
Staged publishing isn't a silver bullet. It won't catch every bad package, and it only works if people use it. But it's a concrete step toward making the npm ecosystem safer. If you're a maintainer, it's worth setting up. If you're a user, it's worth knowing that some packages are now being vetted before they hit your machine.
At the end of the day, this is about control. Control over what you publish, control over what you install, and control over who gets to do either. That's the essence of import/export, and it's good to see npm taking it seriously.
Comments (0)
Please sign in to post a comment.
Don't have an account? Create one
No comments yet. Be the first to comment!