npm Staged Publishing Guide: Secure Package Publishing 2026
Guide · June 2, 2026

npm Staged Publishing Guide:
Secure Package Publishing in 2026

npm just launched staged publishing — the biggest change to package publishing since trustless publishing. This guide covers everything from setup to CI/CD integration to migrating your existing workflows.

Oleg Maximov June 2, 2026 15 min read

What Is npm Staged Publishing?

On May 22, 2026, npm launched staged publishing — a new package publishing workflow that introduces a review gate between packaging a release and making it publicly available on the registry. Instead of running npm publish and having your package go live immediately, you run npm stage publish to submit your package to a staging area. From there, designated reviewers can inspect, approve, or reject the staged release before it ever reaches consumers.

This isn't just a quality-of-life improvement — it's a fundamental shift in npm supply chain security. Staged publishing addresses a critical gap: the moment between "I ran a command" and "the world can install my code." With staged publishing, a compromised CI pipeline or an accidental npm publish with debug code can be caught before it affects your users.

Supported in npm 11.15.0+ and pnpm 11.3+, staged publishing works alongside npm's existing trusted publishing (OIDC-based authentication) and the newer --allow-* install-time controls to create a defense-in-depth strategy for the entire package lifecycle.

Why Staged Publishing Matters

The Supply Chain Security Problem

The JavaScript ecosystem has suffered from supply chain attacks for years. The Mini Shai-Hulud attack earlier this year demonstrated how a single compromised publish token can lead to malicious packages being distributed to millions of users within minutes. Once a package is published, revoking it is painful — npm unpublish has strict time limits (24 hours for most packages), and even when removed, anyone who already installed the malicious version is affected.

Staged publishing solves the time-to-detection problem by creating a mandatory review window. Even a cursory review can catch:

CI/CD Pipeline Protection

Consider a typical GitHub Actions workflow: a merge to main triggers a publish job. If an attacker gains access to your repository secrets (or if a pull request introduces a workflow change that exfiltrates tokens), they can publish a malicious package automatically. With staged publishing, the CI pipeline can only stage a release — a separate approval step (human or automated) is required before the package goes live.

How npm Staged Publishing Works

The staged publishing workflow has three phases:

Phase 1: Stage

Run npm stage publish instead of npm publish. This packages your module and submits it to the staging area on the npm registry. The package is not publicly visible — only you and designated reviewers can see it.

# Traditional (immediate publish)
npm publish

# Staged (submits for review)
npm stage publish

You can optionally add a message describing what this release contains:

npm stage publish -m "v2.1.0: Fixes authentication timeout, adds rate limit headers"

Phase 2: Review

Staged packages can be inspected before approval. Reviewers can:

# View a staged package's manifest and files
npm stage view [email protected]

# List all staged packages (with status)
npm stage ls

# List packages staged by a specific user or CI identity
npm stage ls --by "github-actions[bot]"

The npm stage view command shows the package manifest, file listing with hashes, lifecycle scripts, and any provenance attestations. This gives reviewers full visibility into what's about to be published without downloading or installing anything.

Phase 3: Approve or Reject

Once reviewed, a designated approver either promotes the stage to the live registry or rejects it:

# Approve and publish immediately
npm stage approve [email protected]

# Reject and discard the staged release
npm stage reject [email protected] --reason "Missing changelog entry"

Approvals can be scoped to a specific npm team or individual user. Organizations can require multiple approvers before a stage is promoted (see below).

Configuring Staged Publishing

Per-Package Configuration (package.json)

Enable staged publishing for a package by adding the publishConfig section to your package.json:

{
  "name": "@myorg/awesome-package",
  "version": "2.1.0",
  "publishConfig": {
    "staged": true,
    "access": "public"
  }
}

For more advanced configuration, you can set reviewer requirements:

{
  "publishConfig": {
    "staged": {
      "enabled": true,
      "requiredApprovers": 2,
      "approvalTimeout": 48,
      "notify": ["slack:#npm-releases", "email:[email protected]"],
      "autoApprove": {
        "ciOnly": false,
        "trustedBranches": ["main", "release/*"]
      }
    }
  }
}

Configuration options:

Global / Organization Configuration (.npmrc)

Set organization-wide defaults in your .npmrc:

# ~/.npmrc or .npmrc at repo root
stage-publish=true
stage-required-approvers=2
stage-approval-timeout=48
stage-notify=slack:#npm-releases

For organizations using npm Teams, staged publishing can be configured at the organization level via the npm web interface under Packages → Staged Publishing Settings.

Authentication with Trusted Publishing

Staged publishing works with npm's trusted publishing (OIDC-based, no tokens). When using GitHub Actions, the OIDC token is automatically used for both staging and approval steps:

# No token needed — OIDC handles authentication
npm stage publish --provenance

For token-based authentication, the token must have the publish:stage scope. Legacy tokens with only publish scope can stage but cannot approve — a separate approve scope token is required for promotion.

CI/CD Integration with GitHub Actions

Basic Staged Publishing Workflow

Here's a complete GitHub Actions workflow that stages a package on every push to main, then waits for manual approval:

# .github/workflows/stage-publish.yml
name: Stage Publish

on:
  push:
    branches: [main]
    paths:
      - 'package.json'
      - 'src/**'

jobs:
  stage:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      id-token: write  # For OIDC (trusted publishing)

    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: '22'
          registry-url: 'https://registry.npmjs.org'

      - run: npm ci
      - run: npm test

      - name: Stage publish
        run: |
          npm stage publish \
            --provenance \
            -m "Automated stage: $(git log -1 --pretty=%B)"
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

Environment-Approval Gate

For maximum security, combine GitHub Environments with staged publishing. Stage promotion requires a deployment review in the GitHub UI:

# .github/workflows/promote-stage.yml
name: Promote Staged Package

on:
  workflow_dispatch:
    inputs:
      package:
        description: 'Package name to promote'
        required: true
      version:
        description: 'Version to promote'
        required: true

jobs:
  promote:
    runs-on: ubuntu-latest
    environment: npm-publish  # Requires approval in GitHub UI
    permissions:
      id-token: write

    steps:
      - uses: actions/setup-node@v4
        with:
          node-version: '22'
          registry-url: 'https://registry.npmjs.org'

      - name: View staged package
        run: npm stage view ${{ inputs.package }}@${{ inputs.version }}

      - name: Approve and promote
        run: npm stage approve ${{ inputs.package }}@${{ inputs.version }}
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_APPROVE_TOKEN }}

Automated Review via Playwright / Audit Scripts

Before human review, you can run automated checks on staged packages:

# scripts/audit-stage.js
const { execSync } = require('child_process');

const packageName = process.argv[2];
const version = process.argv[3];

// Fetch stage manifest
const manifest = JSON.parse(
  execSync(`npm stage view ${packageName}@${version} --json`).toString()
);

// Check for lifecycle scripts
if (manifest.scripts?.install || manifest.scripts?.postinstall) {
  console.error('WARNING: Package has lifecycle scripts:', {
    install: manifest.scripts.install,
    postinstall: manifest.scripts.postinstall
  });
  process.exit(1);
}

// Verify file hash consistency
console.log(`✅ All checks passed for ${packageName}@${version}`);
# CI step
- run: node scripts/audit-stage.js "${{ inputs.package }}" "${{ inputs.version }}"

Direct Publish vs Trusted Publishing vs Staged Publishing

Feature Direct Publish Trusted Publishing Staged Publishing
Authentication Token-based (NPM_TOKEN) OIDC (no token needed) OIDC or token
Review Gate None None Required before registry
Time to Live Instant Instant After approval
CI/CD Friendly Yes Yes (no secrets) Yes (stage + approve)
Supply Chain Risk High (one token = full access) Medium (no tokens to steal) Low (review catches malice)
Rollback Before Release Impossible after publish Impossible after publish Easy (reject stage)
Multi-Approver Not supported Not supported Built-in
Provenance Attestation Supported Supported Supported + stage info
npm Version Required >= 6.x >= 9.x >= 11.15.0
pnpm Version Required >= 6.x >= 8.x >= 11.3

Integration with --allow-* Install-Time Controls

npm's --allow-* flags — introduced alongside staged publishing — give consumers fine-grained control over what published packages can do at install time. Together, they create a complete security model:

For organizations, the recommended setup is: staged publishing on the publisher side (prevent bad packages from reaching the registry) + --allow-* controls on the consumer side (limit what packages can do during installation). This defense-in-depth approach ensures that even if a malicious package slips through, its blast radius is contained.

Migration Guide: Moving from Direct Publish to Staged

Step 1: Update npm/pnpm

# Update npm
npm install -g npm@latest

# Or for pnpm users
pnpm add -g pnpm@latest

# Verify
npm --version
# Should show 11.15.0+
pnpm --version
# Should show 11.3+

Step 2: Enable Staged per Package

Add to your package.json:

"publishConfig": {
  "staged": true
}

Step 3: Update publish tokens

If using token authentication, generate a new token with the publish:stage scope. If using trusted publishing (recommended), ensure your CI has OIDC permissions configured.

Step 4: Update CI/CD

Replace npm publish with npm stage publish in your CI workflows. Add a separate approval workflow (or use GitHub Environments / GitLab approval gates for the promotion step).

Step 5: Define approvers

Add team members as designated approvers via the npm web interface. For small teams, the package maintainer is typically the approver. For larger organizations, create a dedicated @releases team.

Step 6: Test the workflow

Run a test stage with a patch version bump. Stage it, inspect it, approve it. Then run npm install your-package from a test project to verify the published package works as expected.

# Test the full flow
npm version patch
npm stage publish
npm stage view your-package@$(node -p "require('./package.json').version")
npm stage approve your-package@$(node -p "require('./package.json').version")

Best Practices for Staged Publishing

1. Require Multiple Approvers for Critical Packages

For packages with millions of weekly downloads or packages that are dependencies of your core product, set requiredApprovers to 2 or more. This ensures no single compromised account can push malicious code.

2. Use Trusted Publishing + Staging Together

Trusted publishing eliminates the risk of stolen auth tokens. Staged publishing adds a review gate. Together, they eliminate the two biggest attack vectors: stolen credentials and unreviewed code.

3. Automate Pre-Approval Checks

Run automated audits on every staged package before human review. Check for unexpected files, new lifecycle scripts, dependency changes, and provenance attestation validity. Only escalate to human review if auto-checks pass.

4. Set Sensible Timeouts

Configure approvalTimeout based on your release cadence. For daily releases, 24 hours is sufficient. For weekly releases, 72 hours gives reviewers the weekend. Stale stages that timeout are automatically discarded.

5. Log All Approvals and Rejections

npm logs every stage action to the audit log. For compliance-sensitive organizations, ensure your .npmrc configuration points to your audit logging endpoint.

Real-World Impact: What Changes

For Open Source Maintainers

If you maintain a popular open source package, staged publishing means you can merge PRs and have CI automatically stage a release — but only you (or your co-maintainers) can flip the switch to make it live. This is especially valuable for projects where CI has publish access but maintainers want a final sanity check.

For Enterprise Teams

For organizations with strict release processes, staged publishing formalizes what was previously an ad-hoc checklist. The npm registry now enforces the review step, removing the possibility of accidental bypass. Combined with the organization-level configuration, enterprises can enforce staged publishing across all their packages.

For Solo Developers

Even if you work alone, staged publishing provides a safety net. Stage your release, take a 5-minute break, then review what you're about to publish with fresh eyes. The number of times I've caught a forgotten console.log with credentials or a test file with API keys... staged publishing would have saved me hours of damage control.

For secure npm and web development services, contact me

FAQ

What is npm staged publishing?
npm staged publishing is a new workflow where packages are submitted to a staging area first using npm stage publish, then reviewed and approved before going live on the registry. It replaces direct npm publish for many workflows, adding a review gate to prevent accidental or malicious releases.
How do I use npm stage publish?
Use npm stage publish instead of npm publish. This submits your package to a staging area. Then use npm stage approve to promote it to the registry, or npm stage reject to discard it. You can review staged packages with npm stage view and list all staged packages with npm stage ls.
What npm version supports staged publishing?
npm version 11.15.0 or later supports staged publishing. pnpm 11.3 and later also supports it. You can check your version with npm --version or pnpm --version.
How is staged publishing different from npm trusted publishing?
Trusted publishing uses OIDC tokens to authenticate npm publish without manual tokens (supply chain security). Staged publishing adds a review gate between packaging and registry publication. They work together: you can use trusted publishing for the npm stage publish step, then have a human or automated reviewer approve the stage promotion. For more on supply chain security, read my analysis of the 2026 npm Mini Shai-Hulud supply chain attack.
Is staged publishing mandatory now?
No, staged publishing is optional as of June 2026. The traditional npm publish workflow continues to work. However, npm recommends staged publishing for organizations managing multiple packages, CI/CD pipelines, and any team wanting stronger supply chain security.
How do I configure staged publishing in package.json?
Add a publishConfig section to your package.json with "staged": true. Optionally configure staged.requiredApprovers (minimum reviewers), staged.approvalTimeout (hours before auto-cancel), and staged.notify (Slack/email on new stages). See the configuration section above for the full schema.
Can staged publishing prevent supply chain attacks?
Yes, it significantly reduces the risk. By requiring human or automated review before a package goes live, staged publishing catches malicious code, exposed secrets, and unintended breaking changes before they reach the registry. Combined with --allow-* install-time controls and provenance attestation, it forms a defense-in-depth strategy against supply chain attacks.

Conclusion

npm staged publishing is a significant step forward for the JavaScript ecosystem. It addresses one of the most critical gaps in package security — the lack of a review gate before publication — while giving teams the flexibility to configure exactly how strict that gate should be.

Whether you're maintaining a small open source utility or managing a registry of private packages for your enterprise, the staged publishing workflow integrates naturally into your existing tooling and CI pipelines. Combined with trusted publishing, provenance attestation, and install-time controls, it completes the picture of modern, secure npm package management.

My recommendation: enable staged publishing today. The migration takes under an hour for a typical package, and the security benefit is immediate. Start with requiredApprovers: 1 for a gentle introduction, then tighten the configuration as your team gets comfortable with the workflow.

If you're looking for expert help migrating your CI/CD pipelines or setting up a secure package publishing workflow, I can help. As a full-stack developer with deep experience in the JavaScript ecosystem, I've helped teams implement secure publishing pipelines from scratch. Reach out to discuss your project.

Contact

Need help with your publishing pipeline?

Whether you're migrating to staged publishing, setting up CI/CD for npm packages, or auditing your supply chain security — I can help. Free consultation.