npm's stage-only token scope puts a human between CI and the registry
Tomás Vega
The npm token in your publish workflow has exactly one job (ship a tarball to the registry) and exactly one problem: it can ship anything to the registry, at any time, without asking. That is the entire npm supply-chain nightmare in one sentence, and it is why every dependency-confusion write-up eventually points back at a leaked CI secret. On September 18, 2026, GitHub started to defuse it. npm granular access tokens now support a new scope, Read and write (stage only), that lets an automated workflow stage a package version for a human to approve, but not publish it.
What the new scope actually lets a token do
A stage-only token can call npm stage publish to push a candidate version into a staging area on the registry. It keeps the useful adjacent permissions a release automation tends to need: moving dist-tags, deprecating versions. Ordinary npm publish with that token is refused. Per the changelog, npm rejects the direct publish attempt even if the token is configured to bypass 2FA for automation, so the "we set bypass on this one for CI" escape hatch does not apply here.
Staged is not published. A package maintainer opens the staged version, reviews it, and approves it with a two-factor challenge. That approval moves the artifact from staged to released. Two identities, two rights: the CI job produces the bits, a person with a physical second factor decides whether they reach installers.
Why this is the shape you want
Signed builds, provenance, SBOMs: all useful, none of them decides whether a version goes live. That decision has been sitting inside a long-lived registry token stored in a CI secret store, and the industry has spent three years learning, in public, that a long-lived registry token stored in a CI secret store is a soft target. Anyone with commit access to a workflow, or read access to the log where the token accidentally echoed once, has held a publish button.
Stage-only shrinks that button. A leaked stage-only token gets an attacker as far as "there is a suspicious 9.9.9 version waiting for a maintainer to approve it." That is a security-incident story worth reading; the current baseline is not.
Where the bypass-2FA clock fits in
npm has been squeezing bypass-2FA tokens for a while. The new scope is opt-in as of September 18, 2026, and it does not touch existing tokens. It exists as a migration path before npm removes direct publishing through bypass-2FA tokens in January 2027. If your release automation still relies on a token that skips 2FA to talk to the registry, you have a clock on your calendar and two documented ways off it: stage-only tokens with a human approval, or trusted publishing (OIDC-federated to the registry, no long-lived token to leak in the first place), which the announcement calls out as the alternative.
Pick one deliberately. Waiting for the deprecation date to pick for you is a fine way to break Friday.
Moving a workflow across
The mechanical part is small. The changelog lists the prerequisites: npm CLI 11.15.0 or later, Node.js 22.14.0 or later, 2FA enabled on the account, publish access to the package. Mint a new token with the stage-only scope, swap it into the CI secret, and change the publish step in the pipeline to run npm stage publish instead of npm publish. The rest is process: decide who approves, where they get notified, and what happens when they are on vacation.
The last part is the one that always bites. A staging pattern that ships fine on Tuesday afternoon and blocks release at 22:00 on a Friday is going to breed pressure to route around it, and the routes people find (a shared approver account, a bot with a full-publish token "for emergencies") are how you end up back where you started.
The catch
Human-in-the-loop only helps if the human is present, awake and paying attention. A maintainer who habitually approves every staged version, on reflex, delivers exactly the security posture of the old token, wrapped in extra clicks. A staging step that is always approved is a rubber stamp with a compliance receipt.
Wire it up anyway. Then treat "how carefully we review staged versions" as its own ops metric, not an assumption.
Source: GitHub Changelog (github.blog)