Security & supply chain

npm's stage-only token scope puts a human between CI and the registry

npm's stage-only token scope puts a human between CI and the registry

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)

Related
Security & supply chain

npm walls off 2FA-bypass tokens from account and package management

As of July 31, npm granular access tokens configured to bypass 2FA can no longer perform sensitive account, organisation or package management actions. Those calls now demand an interactive 2FA challenge, and the same tokens are on a January 2027 timer to lose direct publish rights too.

August 1, 2026
Supply chain security

npm v12 flips install-time to closed-by-default

npm v12 shipped as latest on July 8, 2026, with lifecycle scripts, git-URL dependencies and remote-URL dependencies all off by default at install time. Alongside it, the 2FA-bypass Granular Access Token starts a two-step retirement that ends direct publishes.

July 9, 2026
Security & supply chain

Docker's fourth horror story revisits the Nx post-install hook that drained CI secrets

The fourth installment of Docker's Coding Agent Horror Stories, published July 28, revisits the August 2025 s1ngularity compromise of the Nx npm package. The lesson for CI/CD teams has nothing to do with coding agents. It is about the post-install hook that ran telemetry.js on every runner that pulled the package.

July 29, 2026

Turn this into your pipeline. Build it on Buddy.

Start free