Trusted publishing and provenance

npm · Advanced · 12 min

Stolen publish tokens are behind many npm supply-chain attacks.

Classic automation published with long-lived tokens stored as CI secrets. Leak one and an attacker can publish malware under your name. The registry now offers better options:

Trusted publishing (OIDC): you register a trust relationship between the package and a CI workflow (GitHub Actions, GitLab CI/CD and others) on npmjs.com or with npm trust github ... (npm 11.15+). In CI, npm publish exchanges the CI provider's short-lived OIDC identity token for a publish credential. There is no npm token to store, rotate or leak. In GitHub Actions the job needs permissions: id-token: write.

Provenance: packages published from supported CI with trusted publishing get a signed provenance attestation automatically (or use npm publish --provenance with token-based CI publishing). It links the tarball to the source repository, commit and workflow that built it, recorded in the public Sigstore transparency log. The npm website shows a provenance badge; consumers verify with npm audit signatures.

Staged publishing (npm stage publish) lets CI upload a version that stays unavailable until a maintainer approves it with 2FA, restoring a human check for automated releases.

Also: require 2FA for publishing in package settings, prefer granular access tokens with short expiry where tokens are unavoidable, and limit maintainers.

Example

# .github/workflows/release.yml
name: release
on:
  push:
    tags: ["v*"]
permissions:
  contents: read
  id-token: write          # lets npm obtain a GitHub OIDC token
jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
      - uses: actions/setup-node@v5
        with:
          node-version: 24
          registry-url: https://registry.npmjs.org
      - run: npm ci
      - run: npm test
      - run: npm publish --access public   # no NPM_TOKEN: trusted publishing + provenance

Remember

  • Trusted publishing swaps CI OIDC tokens for publish rights: no stored secret
  • Provenance links a tarball to its repo, commit and workflow
  • Staged publishing adds a 2FA approval to automated releases
  • Consumers verify with npm audit signatures

Watch out for

  • Keeping a long-lived automation token in CI secrets after moving to trusted publishing.

Check yourself

  1. What does a provenance attestation let consumers verify?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: docs.npmjs.com/trusted-publishers