On 18 September 2026, npm added a new permission for granular access tokens: "Read and write (stage only)". A token with it can submit a package version for review with npm stage publish, but npm refuses a direct npm publish with that token, even if it is set to bypass two-factor authentication. GitHub's changelog adds that npm is targeting January 2027 to remove direct publishing through 2FA-bypass tokens entirely. Two follow-ups landed within two weeks: dist-tag management over OIDC on 30 September, and staged creation of brand new packages on 2 October.
What's affected
This is a registry policy change, not a vulnerability. It affects every team that publishes to npm from automation using a long-lived token, which is the token that worms like the 2026 Shai-Hulud variants steal and reuse.
What changed, per GitHub's changelogs and the npm docs:
- Stage-only tokens (18 September). Choose "Read and write (stage only)" when creating a granular token. Automation runs
npm stage publish. A maintainer then approves the version with 2FA, in the CLI or on npmjs.com. Stage-only tokens can still move dist-tags and deprecate versions, so protect them like any write token. Existing tokens are unchanged. - Requirements. Publish access to the package, 2FA on the npm account, npm CLI 11.15.0 or later and Node.js 22.14.0 or later.
- Dist-tags over OIDC (30 September). Each trusted publishing configuration has an "Allow npm dist-tag" setting. It is off by default for new and existing configurations. When on, the workflow can move
latest,nextorbetawith a short-lived OIDC credential instead of a stored token. - Staged creation of new packages (2 October).
npm stage publishcan now create a package that doesn't exist yet. The registry publishes a public placeholder version0.0.0-stage, and the real first version waits for a maintainer's approval.
The design point is simple. Staging never prompts for 2FA and works with any token type. Approving does prompt for 2FA. So a stolen CI token can at worst queue a version that a human then has to approve.
How to check if you're exposed
Find where your pipelines publish and what credential they use:
grep -rnE 'npm publish|NPM_TOKEN|NODE_AUTH_TOKEN|_authToken' .github/workflows/ .gitlab-ci.yml .circleci/ 2>/dev/null
Then review the tokens on your npm account in the web UI under Access Tokens. For each granular token, note its package scope, whether it bypasses 2FA, and its expiry. Any token that can publish directly and lives in a CI secret is the one to replace.
Confirm your tooling meets the minimums before you switch:
npm --version # needs 11.15.0 or later
node --version # needs 22.14.0 or later
What to do now
-
Prefer trusted publishing where you can. GitHub's changelog says trusted publishing is the preferred path, and stage-only tokens are the migration route for teams that can't switch yet. With trusted publishing there is no token to steal.
-
Where you still need a token, make it stage-only. Create a new granular token with "Read and write (stage only)", limited to the packages that pipeline publishes, with an expiry. Replace the secret and change the release step:
# before npm publish --access public # after npm stage publish -
Approve with 2FA, after looking. Use the review commands before approving:
npm stage list your-package npm stage view STAGE_ID npm stage download STAGE_ID # inspect the tarball npm stage approve STAGE_ID # prompts for 2FA -
Move dist-tag jobs to OIDC. If you kept a token only to run
npm dist-tag addafter releases or rollbacks, turn on "Allow npm dist-tag" for that trusted publishing configuration and delete the token. -
Retire bypass-2FA publish tokens before January 2027. Treat that date as a target, as GitHub does, but plan as if it holds. Revoke each old token once its pipeline is migrated.
Why it matters
The Shai-Hulud style worms seen on npm in 2026, including the October tensorlake compromise, follow the same path: steal a publish token from a developer laptop or CI job, then push new versions of every package that token can reach. Short-lived OIDC credentials and a human approval step each break that chain. A stolen stage-only token still lets an attacker queue a release and move dist-tags, so it is not harmless, but it no longer turns one infected machine into dozens of poisoned packages within minutes.
Approval only helps if someone looks. Build a short review habit around it: diff the staged tarball against the previous version, check for new install scripts and new dependencies, and confirm the version matches a tag in your repository.
Try it yourself
Take one package you publish and compare the last two versions' tarballs. Look specifically at scripts in package.json and at any new files that run at install or import time. That is the review you'd do on every npm stage approve, and timing it tells you whether staged publishing will fit your release cadence.
Click through it at your own pace, or open it full screen.
Quick check
What happens if a stage-only token runs npm publish?
npm rejects it, even if the token is configured to bypass 2FA. The token can only submit versions with npm stage publish, which a maintainer must approve with 2FA.
Can a stage-only token do anything else with write access?
Yes. It can still move dist-tags and deprecate versions, so it needs the same protection as any write token.
Is OIDC dist-tag management on by default?
No. The "Allow npm dist-tag" setting is off by default for new and existing trusted publishing configurations.