npm Stage-Only Tokens Add a Human Release Gate—but Remain Write Credentials
📌 Key Takeaways
- Separate submission from release: npm’s
Read and write (stage only)token decouples automated candidate submission (npm stage publish) from public distribution, enforcing an interactive 2FA human maintainer gate. - Keep protecting the token: The token is not a read-only or harmless upload key; it retains package-write capabilities including mutating
dist-tagsand deprecating active versions. - Choose authentication and approval separately: Authentication method (OIDC trusted publishing vs long-lived secrets) and release authority (direct publish vs staging) must be evaluated and configured as separate governance controls.
npm’s Read and write (stage only) granular-token permission divides a release into two authorities: automation may submit a new package version to staging, but a maintainer must complete two-factor authentication before that version becomes public. A direct npm publish is rejected rather than converted into a staged submission. The new credential reduces CI’s publication authority, but it does not turn CI access into a harmless upload key: npm says the token retains package-write capabilities including moving dist-tags and deprecating versions. (GitHub Changelog, September 18, 2026; npm Registry API)
The practical decision has two independent parts:
- Authentication: Should the workflow use a stored npm token or OIDC trusted publishing?
- Release authority: Should the workflow publish immediately or only stage a candidate for human approval?
OIDC addresses the standing-secret problem. Staged publishing addresses whether CI may finish a release without a maintainer. A team can—and, where supported, often should—use both. (npm trusted-publishing documentation; npm staged-publishing documentation)
What the stage-only permission actually enforces
The npm website labels the permission Read and write (stage only). In the Registry API, the corresponding packages_and_scopes_permission value is:
read-write-stage-only
A token with that permission may submit a package version through npm stage publish, backed by POST /-/stage/package/{package-name}. It may not publish a new version directly through the standard publish endpoint. If the request reaches the publish-policy check, the documented response is HTTP 403 with E_STAGE_REQUIRED; earlier authentication or authorization checks may produce different errors. npm explicitly states that a rejected direct publish is not automatically redirected to staging. (npm Registry API; GitHub Changelog, September 18, 2026)
That behavior remains in force even if the token was configured with bypass_2fa: true. The bypass setting applies only to automation flows allowed by the token’s package permissions and publish policy; it does not let a stage-only token publish directly or approve its own staged version without the required maintainer step. (npm Registry API; GitHub Changelog, September 18, 2026)
On narrow screens, swipe horizontally to inspect the full diagram.
Illustrative workflow—not test evidence: npm stage publish creates a reviewable candidate, maintainer approval with 2FA promotes it to the public registry, and a direct npm publish ends at 403 E_STAGE_REQUIRED rather than falling through to staging.
The security boundary is narrower than “no write access”
Confirmed: npm continues to classify the credential as a package-write token. Its documentation names two retained capabilities: changing dist-tags and deprecating versions. The token should therefore remain subject to package scoping, secret storage, expiration, revocation, monitoring, and incident-response controls appropriate to a write credential. (GitHub Changelog, September 18, 2026; npm Registry API)
Reasonable inference: Compromise of a stage-only token removes one high-impact path—unilateral publication of a new package version—but does not remove every way an attacker might disrupt an existing package. Moving a dist-tag can change which already-published version a consumer receives under that tag, while deprecation changes the package metadata presented to users. The cited sources do not provide an exhaustive inventory of every writable operation available to this permission, so the broader residual-risk boundary remains open. (npm Registry API; GitHub Changelog, September 18, 2026)
The release now has a reviewable intermediate state
npm documents staged publishing as a three-part flow:
- Stage:
npm stage publishsubmits the package version without requiring 2FA. - Review: Maintainers can list visible staged versions, inspect a specific record, and download its tarball.
- Approve:
npm stage approve <stage-id>or the approval control on npmjs.com prompts for 2FA before publishing the version to the live registry.
The Registry API additionally exposes operations to list staged records, retrieve details and tarballs, approve records, and delete them. Approval moves the candidate into the published state; deletion removes the staging record so it cannot be approved unless submitted again. (npm staged-publishing documentation; npm Registry API)
On a small screen, swipe across the diagram to follow all four steps.
Documented prerequisites
For the staged-publishing workflow, npm specifies these minimum conditions:
- npm CLI 11.15.0 or later
- Node.js 22.14.0 or later
- Publish access to the package
- 2FA enabled on the maintainer’s npm account
- An existing package on the npm registry
The user guide states unambiguously that a brand-new package cannot be staged. It also distinguishes the noninteractive staging action from approval: npm stage publish does not require 2FA, while approval through either the CLI or npmjs.com does. (npm staged-publishing documentation; GitHub Changelog, May 22, 2026)
OIDC and staging solve different problems
Trusted publishing uses OIDC to authenticate a known CI/CD workload without placing a long-lived npm publishing token in that workflow. npm’s implementation accepts identity from an authorized workflow and uses short-lived, cryptographically signed credentials for publication. OpenSSF describes the general model as exchanging an OIDC identity token for a short-lived, tightly scoped repository credential. (npm trusted-publishing documentation; OpenSSF trusted-publisher guidance)
Staging instead controls the action that the authenticated workflow may complete. Current npm trusted-publisher configurations always permit npm stage publish; direct npm publish is an additional, opt-in action for newly created configurations. npm therefore supports OIDC for either direct publication or staged submission. (GitHub Changelog, September 3, 2026; npm trusted-publishing documentation)
| Workflow design | Stored publishing secret | Can CI make a new version public by itself? | Best fit |
|---|---|---|---|
| Granular write token + direct publish | Yes | Yes | Unattended release is necessary and the reusable-secret risk is accepted |
| Stage-only granular token | Yes | No | OIDC is unavailable, but human release approval is required |
| OIDC + direct publish | No long-lived publish token | Yes | Supported CI should complete releases unattended |
| OIDC + staged publish | No long-lived publish token | No | Both the standing secret and unilateral CI release should be removed |
On narrow screens, swipe horizontally to inspect the full diagram.
Neither diagram nor comparison table measures release speed. Authentication determines whether CI stores a reusable npm credential; publication policy independently determines whether CI may complete the release. A human approval queue introduces an operational dependency that should be evaluated in your own workflow, not inferred from an illustrative chart.
Supported trusted-publishing environments
npm currently documents trusted publishing for:
- GitHub Actions on GitHub-hosted runners
- GitLab CI/CD on GitLab.com shared runners
- CircleCI cloud
Self-hosted runners are not currently supported. Trusted publishing requires npm CLI 11.5.1 or later and Node.js 22.14.0 or later; using the staged workflow raises the npm CLI minimum to 11.15.0. (npm trusted-publishing documentation; npm staged-publishing documentation)
OIDC narrows credential lifetime and removes the need to distribute a standing publish token, but it does not eliminate workflow risk. OpenSSF cautions that temporary credentials remain sensitive while valid and that the identity provider, trust policy, and authorized workflow state must be protected. In other words, trusted publishing changes the credential model; it does not make a compromised authorized workflow consequence-free. (OpenSSF trusted-publisher guidance; npm trusted-publishing documentation)
Migration requires changing the command, not just the credential
Replacing an existing write token with a stage-only token while leaving npm publish in the workflow produces a rejected release, not a staged candidate. The release job must explicitly invoke:
npm stage publish
A migration should therefore treat the command path, authentication method, and approval ownership as separate configuration items. (npm Registry API; GitHub Changelog, September 18, 2026)
Practical migration sequence
-
Inventory release jobs. Identify workflows using granular tokens, especially tokens configured to bypass 2FA, and record whether each workflow genuinely requires unattended publication.
-
Adopt OIDC where the supported provider and runner constraints fit. npm recommends configuring and verifying trusted publishing before restricting token access and revoking superseded automation tokens.
-
Choose publication authority independently. Enable direct
npm publishonly when autonomous release completion is intentional. Otherwise retain stage-only permission and assign responsibility for review, 2FA approval, rejection, and maintainer absence. -
For token-based staging, change both controls. Select Read and write (stage only) for the required packages or scopes and replace
npm publishwithnpm stage publish. -
Keep the token in the write-risk inventory. Monitor dist-tag changes and deprecations, scope the credential narrowly, and preserve a tested revocation path. (npm trusted-publishing documentation; GitHub Changelog, September 18, 2026)
The 2026–2027 transition is opt-in before it is mandatory
On July 31, 2026, npm restricted granular access tokens configured to bypass 2FA from performing several sensitive operations without an interactive challenge:
- Creating or deleting tokens
- Changing package access, maintainers, or trusted-publisher configuration
- Managing organization or team membership
- Managing package grants
On September 18, 2026, npm introduced the stage-only granular-token permission as an opt-in migration path. The release did not modify existing tokens or remove their direct-publish capability. (GitHub Changelog, July 31, 2026; GitHub Changelog, September 18, 2026)
npm says it is targeting January 2027 for bypass-2FA granular tokens to lose direct publication. After that planned change, npm describes their publishing surface as reading private packages and staging a publish for later 2FA approval. “Targeting” identifies npm’s stated schedule; it is not a guaranteed cutoff date. (GitHub Changelog, July 31, 2026; GitHub Changelog, September 18, 2026)
Which npm operations remain available?
The first two columns summarize the documented permission boundary. The last column is our operational recommendation, not an additional npm requirement.
| Operation | Stage-only boundary | Suggested team control |
|---|---|---|
| Stage a version | Allowed through npm stage publish; submission itself does not require 2FA. | Record the candidate ID, source revision, and package version so the reviewer can identify the intended release. |
| Publish directly | Blocked with this token, including when it is configured to bypass 2FA. | Treat rejection as a configuration failure. Do not silently retry with a more powerful credential. |
| Approve a candidate | Requires an authorized maintainer and interactive 2FA; the stage-only token cannot complete that step by itself. | Assign an approver and a backup maintainer. A separate two-person organizational rule is optional, not a requirement established by these sources. |
| Move a dist-tag | Retained package-write capability. | Monitor changes to tags such as latest; retain the previous version mapping for incident review. |
| Deprecate a version | Retained package-write capability. | Review deprecation messages and investigate unexpected metadata changes, even when no new version was published. |
Scope: these are the operations relevant to this release decision, not an exhaustive API permission inventory. Sources: npm stage-only announcement and staged-publishing guide.
Planning note: the January 2027 date above is a target, not a confirmed cutoff. The operation table separates current documented permissions from suggested team controls; it does not describe a new npm approval policy.
One documentation conflict remains unresolved
Open question: npm’s staged-publishing user guide says the package must already exist and that a brand-new package cannot be staged. The Registry API’s staging endpoint says a package must “exist or be creatable by the authenticated publisher,” yet the same endpoint documents 404 Not Found when the specified package does not exist. These statements are not fully aligned. (npm staged-publishing documentation; npm Registry API)
Until npm reconciles the wording, the defensible implementation assumption is the narrower user-guide requirement: use staged publishing for an existing package, not for its first publication. That is an operational interpretation of conflicting documentation, not a verified capability limit beyond the cited sources.
Proposed validation before production rollout
The following checks are proposed and have not been performed by Tech Trend Insight:
- With a disposable existing package, verify successful staging, tarball inspection, 2FA approval, and staged-record deletion.
- Confirm that direct
npm publishwith a stage-only token reaches the documented403 E_STAGE_REQUIREDpolicy failure. - Test documented residual operations—dist-tag modification and deprecation—with a narrowly scoped disposable credential.
- Run a canary through the organization’s actual monorepo or release tool to observe how it handles stage IDs, approval state, and partial multi-package failures.
- In a controlled namespace, attempt staging a deliberately new package and record the exact client versions, account state, package state, and API response; do not generalize one result into an undocumented product guarantee.
Each exercise should use a disposable package or namespace, record npm and Node.js versions, and revoke the test credential afterward. The primary documentation establishes npm CLI and Registry API behavior, but it does not establish compatibility behavior for every third-party release orchestrator. (npm staged-publishing documentation; npm Registry API)
Decision rule
Use OIDC trusted publishing when npm supports the CI provider and runner, because it removes the long-lived publishing token from the workflow. Separately require staged publication when CI should not possess unilateral authority to release a new version.
If OIDC is unavailable, a package-scoped stage-only token is a meaningful reduction in publication authority. It is still a write credential, however, and must be governed as one. (npm trusted-publishing documentation; GitHub Changelog, September 18, 2026)
Frequently Asked Questions (FAQ)
Does switching to a stage-only token protect against compromised CI pipelines?
It blocks direct publication of a new version using that stage-only token; it does not eliminate the risk from a compromised CI pipeline. An attacker may still stage a malicious candidate, move dist-tags, or deprecate existing versions. Other credentials and compromised maintainer accounts are outside this token’s protection. Where supported, OIDC can replace the stored token while staged publication preserves the approval step. Package scoping, careful review, and monitoring remain necessary controls.
Why does direct npm publish fail with HTTP 403 E_STAGE_REQUIRED instead of auto-staging?
The documented behavior is rejection, not automatic conversion to staging. When the request reaches the publish-policy check, the Registry API documents HTTP 403 with E_STAGE_REQUIRED; an earlier authentication failure may produce a different response. The practical implication is that migration must change the command as well as the credential. Treat this as documented behavior, not evidence of an undocumented security guarantee about the staging queue.
Can a brand-new package be published using the staged workflow?
For production planning, follow the user guide’s existing-package requirement: it says a brand-new package cannot be staged. The Registry API wording is not fully aligned, as discussed above, and we have not tested that edge case. Do not build first-publication automation around the broader API wording without confirmation from npm or a controlled validation.
What happens to tokens configured with bypass_2fa in January 2027?
npm is targeting January 2027 to remove direct publication capabilities from bypass-2FA granular tokens. After that planned milestone, those credentials will only be permitted to read private packages and stage candidates for interactive maintainer 2FA approval.