Skip to main content

npm's Staged Publishing: A Step Toward Safer Cloud Migrations

npm's new staged publishing adds human review before packages go live, curbing supply chain attacks. Here's why it matters for cloud migration workflows.

The Supply Chain Wake-Up Call

If you've been migrating anything to the cloud, you know the drill: you set up CI/CD, push code, and hope the artifacts you pull from the registry aren't poisoned. The past few months have been brutal. The Shai-Hulud worm tore through npm, and then npm deprecated traditional tokens in favor of a more secure scheme. These incidents weren't just noise—they forced a fundamental rethink of how packages get from a developer's machine to production.

npm's answer is staged publishing. It's a simple idea with big implications: before a package version goes live, a human has to explicitly approve it. No more instant gratification. No more 'push and pray.'

How Staged Publishing Works

Instead of publishing directly, the package tarball is uploaded to a staging queue. You can see it in the npm website and in the CLI. Then, a maintainer with 2FA enabled has to approve it. The staging step itself doesn't require 2FA, which is a thoughtful touch—it means your non-interactive CI pipelines won't break. The identity check happens only at the approval step.

Here's the workflow:

  • npm stage publish — submit the version to the queue
  • npm stage list — see what's waiting
  • npm stage view <stage-id> — inspect the tarball
  • npm stage approve <stage-id> — promote it, with 2FA
  • npm stage reject <stage-id> — discard it

You'll need npm CLI 11.15.0+ and Node 22.14.0+, and the package must already exist in the registry. The CLI flags like --tag and --provenance behave just like npm publish, so the learning curve is minimal.

Why This Matters for Cloud Migration

Cloud migration isn't just about lifting and shifting virtual machines. It's about rearchitecting your build and deployment pipelines. If you're moving to a microservices architecture, you're probably using npm packages for shared libraries, utilities, or even serverless functions. Every dependency is a potential attack vector.

Staged publishing gives you a chance to catch malicious code before it reaches your production environment. In a cloud-native world, where everything is automated, adding a manual approval step might feel like a step backward. But it's a deliberate pause that can save your bacon.

The Security Angle: OIDC and Trusted Publishing

GitHub recommends combining staged publishing with OIDC-based trusted publishing. The idea is to configure your CI so it can only stage packages, not publish them directly. That way, even if an attacker hijacks your CI, they can't push a rogue package to npm. They'd have to get past the human approval gate.

Security researcher Adnan Khan put it bluntly: 'All developers publishing to npm should enable this feature.' He's not wrong. If you're using OIDC in CI, you can now add a human review before the package goes public. That's a huge step up from the old model.

Not everyone is convinced. Hacker News user weinzierl called it 'a band-aid' that might distract from building better infrastructure. But a reply shot back: 'How could it possibly be harmful?' The point is that it closes a massive hole: CI hijacking. Attackers might find other ways, but this is a big one.

Adoption and Pushback

Some worry that staged publishing only works if maintainers actually use it. True. But npm could make it the default in the future. There's precedent—npm is already planning to make fine-grained access tokens that bypass 2FA default to 'stage-only' in a future release.

On Reddit, a commenter said this only slows down the spread of malicious packages, not a cure. That's fair. But slowing down malware is better than nothing. And it's not just npm—pnpm 11.3 added pnpm stage with the same subcommands, and Yarn has a similar feature. release-it supports a "stage": true option. The ecosystem is moving together.

Practical Tips for Your Pipeline

If you're adopting staged publishing, start small. Pick a non-critical package, set up the staging queue, and get your team used to the approval flow. Make sure your CI uses OIDC, and configure it to only stage, not publish. Update your npm CLI and Node version.

Also, consider the new flags in the latest npm: --allow-file, --allow-remote, and --allow-directory. These control what kinds of dependencies can be used, and they can be set to all or none in .npmrc or package.json. In npm v12, --allow-git will default to none, meaning Git dependencies will be blocked by default. That's a big deal for supply chain security.

The Road Ahead

GitHub has more plans: they'll add an allowScripts field in v12 to disable install scripts by default. That would be a massive change, because many attacks rely on malicious install scripts. If you're migrating to the cloud, you should be thinking about these defaults.

Staged publishing isn't a silver bullet. But it's a practical, incremental step that makes it harder for attackers to slip malicious code into your supply chain. And in the cloud migration world, where you're already dealing with a lot of moving parts, any extra layer of security is welcome.

So, the next time you're setting up a new pipeline, consider staging your publishes. It might feel like a hassle, but it's a small price for peace of mind.

Share this article:

Comments (0)

No comments yet. Be the first to comment!