News

npm Stage-Only Tokens Are Here: Move Token-Based Publishing to Staged Releases Before January 2027

npm now offers a granular access token that can stage a version but is rejected for direct publishing, and it plans to remove direct publishing through bypass-2FA tokens in January 2027. Inventory every publish token your pipelines and AI release agents hold, run one stage-and-approve test, and record a decision per package.

2026-09-19

A padlocked chain-link gate in a dark industrial hall with a black crate on the wet floor in front of it, lit orange on the left and blue on the right.
The locked gate stands for the maintainer's 2FA approval: a staged package waits outside it until a person opens the way to the registry.

What Changed on September 18

GitHub's September 18, 2026 changelog adds a new permission option for npm granular access tokens: Read and write (stage only). A workflow holding such a token submits a version with npm stage publish. The registry rejects a direct npm publish with that token even if 2FA bypass is configured on it. A maintainer then reviews the staged version and approves it with two-factor authentication.

Two details decide how much this helps you. First, the feature is opt-in: nothing changes for a token you already hold until you create a new one with the stage-only permission. Second, npm targets January 2027 to remove direct publishing through bypass-2FA tokens. The changelog states that as a target, not a switch-off date, so treat it as a planning deadline rather than a guaranteed cut-over.

Note what a stage-only token still can do. The changelog says it retains other package write permissions, and names moving dist-tags and deprecating versions. A stage-only token is a narrowed publish route, not a read-only credential. If an agent could move latest to an older version with it, that is still a release action your review has to cover.

Check versions before you test

Both the changelog and the npm staged publishing documentation require npm CLI 11.15.0 or later and Node.js 22.14.0 or later, 2FA enabled on the account, and publish access to the package. The documentation adds that the package must already exist on the registry. Record the installed CLI and runtime versions on every runner before you attribute a failure to the token.

Which Pipelines Are Affected

The route being retired is any automation that authenticates with a granular access token that has 2FA bypass enabled and runs npm publish directly. That covers classic CI release jobs, semantic-release or changesets bots, monorepo publish scripts, and any AI release agent that has been given an NPM_TOKEN secret so it can cut releases without a human present. The agent case deserves attention because the token is often created once, shared across several packages, and never listed in the agent's tool inventory.

Pipelines already on trusted publishing are outside this change. OIDC connections are owned by our npm trusted publisher audit, which covers the union-of-permissions problem and the staged-versus-direct decision per connection. This page owns the token route only: which tokens exist, what they can do, and how to move each one to a staged release or out of service. The documentation notes that staged publishing also works with OIDC and still requires a maintainer's 2FA approval; if you are choosing between the two routes, read both pages before deciding.

Build the Token Inventory

List every publish-capable token the way you would list every secret reaching a privileged step: from the registry side and from the consumer side, then join the two. On the npm side, review each maintainer account's granular access tokens and their permission type. On the consumer side, search CI secrets, agent configurations, and .npmrc files for token references. Name the reference, never the value.

git grep -n -E 'NPM_TOKEN|_authToken|npm publish' -- '**/.github/workflows/*' '**/.npmrc' '**/package.json' '**/release*.{js,mjs,sh,yml,yaml}'

One row per package and token. Last use comes from the pipeline's run history or the token's last-used field on npm, whichever you can date. Give every row an owner and a removal date, and treat a row without last-use evidence as active until you can prove otherwise.

PackageToken reference and holderPermission typeLast useReplacement route
example/sdkNPM_TOKEN_SDK, release.ymlRead and write, bypass 2FA2026-09-12, run 4812OIDC, staged; token retired after positive test
example/cliNPM_TOKEN_CLI, AI release agentRead and write, bypass 2FA2026-09-16, agent session logStage-only token; maintainer approves with 2FA
example/internal-toolNPM_TOKEN_LEGACY, no active consumer foundRead and write, bypass 2FANo evidence since 2026-03Retire; revoke and re-run the consumer search
example/docs-themeNPM_TOKEN_DOCS, publish.shRead and write, 2FA required2026-08-30, manualUnaffected by the bypass change; still decide stage-only or OIDC

The rows are illustrative, not npm defaults. The point of the last column is that the answer differs per package: a token nobody uses should be revoked, not migrated, and a token that already requires 2FA is not touched by the January 2027 plan even if you decide to narrow it anyway.

Run a Stage-and-Approve Test

Use a dedicated test package with harmless content, kept out of real dependency graphs. The following is a proposed method, not a report of a test performed for this article. Because the documentation requires an existing package, create it once with an ordinary publish from a maintainer session before any token test. Then create a granular access token with the stage-only permission scoped to that package alone, and store it as the only registry credential on the test runner.

  1. Positive stage: bump to a fresh version and run npm stage publish with the stage-only token. Expect a staged version, and confirm with npm stage list <package> that it is listed and not installable at that version.
  2. Negative direct publish: with the same token and another fresh version, run npm publish. Expect the registry to reject the attempt; record the sanitized error and verify the version is absent from the registry.
  3. Review: inspect the candidate with npm stage view <stage-id> and, if you need the tarball, npm stage download <stage-id>. Compare the contents with the source revision that produced it.
  4. Approve: a named maintainer runs npm stage approve <stage-id> or uses the Staged Packages tab and the Approve button on npmjs.com. Both paths require 2FA. Confirm the version is now installable and which dist-tag it received.
  5. Residual write check: with the stage-only token, attempt a dist-tag move on the test package. The changelog says this remains permitted; record the observed result so your review covers it.

Keep the positive and negative cases identical except for the command. Classify a duplicate-version error, an outdated CLI, or a registry timeout as inconclusive, not as a passing negative. The sources do not say how long a staged version is retained or how to discard one, so note what you observe rather than assuming a rule.

package: @example/stage-test
token_ref: NPM_TOKEN_STAGE_TEST (stage only, scoped to one package)
cli: 11.15.0   node: 22.14.0
positive_stage: 0.0.3 staged, stage-id recorded
negative_publish: 0.0.4 rejected, not on registry
approval: npm stage approve, 2FA, approver named
approved_state: 0.0.3 installable, dist-tag latest
dist_tag_move_with_token: permitted (observed)
decision_for_production: stage-only token for example/cli

Decide per Package: OIDC, Stage-Only Token, or Retire

Retire the token when the inventory shows no consumer or a consumer you can delete. Revoke it, re-run the consumer search, and watch the next scheduled release for a failure that reveals an undocumented user. This is the cheapest outcome, and it is worth checking first for tokens created before your organization adopted CI.

Move to OIDC when the release runs from a CI provider npm supports for trusted publishing and you can name the repository, workflow, and environment. Do that migration under the audit on the trusted publisher page, and revoke the token only after the OIDC route has passed its own positive and negative tests. Two working routes for one package is the state you are trying to leave.

Keep a stage-only token when the publisher cannot use OIDC, for instance an AI release agent that runs outside a supported CI identity, or a self-hosted job you are not ready to move. The agent submits a candidate; a maintainer approves with 2FA. Because the token still permits dist-tag moves and deprecation, pair it with the agent rollback and approval plan so an unexpected tag change has a defined response, and keep the wider tool boundary in the zero-trust architecture guide for AI agents.

Whichever route you pick, write it into the inventory row with an owner and a date. Schedule one review after the migration and one in early January 2027 to confirm that no bypass-2FA token remains attached to an active pipeline. The goal is to reach npm's target month with every token either narrowed to staging, replaced by an identity, or gone, and with a test another maintainer can repeat on the same package.

Sources checked 2026-09-19