npm Trusted Publishing is a column now

v1.7.0 added a Provenance column to proof-of-commitment. Here’s what npm Trusted Publishing actually is, how to turn it on, and what it does (and doesn’t) tell you about a package’s supply chain.

npm has had provenance attestations since 2023. When a package uses Trusted Publishing, the registry records a signed statement that this exact tarball was built by a specific GitHub Actions workflow on a specific commit. You can verify it. The badge shows up on the registry page.

But registry pages are where packages go to be admired, not where they get installed. By the time you run npm install, you’re looking at a lock file, not a browser tab. The provenance badge might as well not exist.

v1.7.0 puts that signal where you can actually see it: in the CLI output, next to the risk score.


What Trusted Publishing actually is

The standard npm publish flow requires a personal access token (PAT) stored as a CI secret. The token authenticates the publisher. If a maintainer’s machine is compromised or the token leaks from a CI log, an attacker can publish a malicious version. The published artifact traces back to a human identity, not to a specific build.

Trusted Publishing replaces the token with OIDC. During a GitHub Actions run, the workflow requests a short-lived identity token from GitHub’s OIDC provider. npm verifies that token against pre-configured expectations: this specific repository, this specific workflow file, optionally this specific environment. If everything matches, npm issues a short-lived publish token automatically. No long-lived secret needed.

The result is a signed attestation attached to the package version. That attestation links the published tarball to a specific commit SHA and workflow run. Anyone can verify it. The provenance chain is now: tarball → workflow run → commit → source code.


How to set it up

Three changes from the typical setup. First, your publish workflow needs the OIDC token permission:

permissions:
  id-token: write
  contents: read

Second, pass --provenance to the publish command:

- name: Publish
  run: npm publish --provenance --access public

Third, remove NPM_TOKEN from your secrets and configure Trusted Publishing in your npm account settings instead. Under your package settings on npmjs.com, add a new trusted publisher and point it at your repository and workflow file.

After publishing, the attestation shows up at: registry.npmjs.org/-/npm/v1/attestations/[package]@[version]


The column in practice

Running npx proof-of-commitment axios chalk zod after v1.7.0:

Package               Risk            Score    Publishers    Downloads     Age       Provenance
───────────────────────────────────────────────────────────────────────────────────────────────
chalk                 πŸ”΄ CRITICAL     75       1             439.6M/wk     12.8y     -
  ↳ 30+ GitHub contributors, publish-access concentration risk despite active community
axios                 πŸ”΄ CRITICAL     88       1             108.0M/wk     11.7y     πŸ” verified
  ↳ 30+ GitHub contributors, publish-access concentration risk despite active community
zod                   πŸ”΄ CRITICAL     88       1             142.7M/wk      6.2y     πŸ” verified
  ↳ 30+ GitHub contributors, publish-access concentration risk despite active community
───────────────────────────────────────────────────────────────────────────────────────────────

⚠ 3 CRITICAL packages found.
   CRITICAL = sole npm publisher + >10M weekly downloads (publish-access concentration risk)
   πŸ” 2/3 use Trusted Publishing (OIDC provenance), partial mitigation

Axios and zod use Trusted Publishing. Chalk doesn’t. All three are flagged CRITICAL because provenance doesn’t eliminate the concentration risk (one npm publisher account controls the release).

That’s the honest read: provenance tells you about the build pipeline, not about the human controlling it. Axios with provenance is still 108 million weekly downloads going through one publisher account. Better than without. Not solved.


Where this fits with --fail-on

v1.7.0 also shipped the --fail-on flag via PR #6, which lets you make CI fail on CRITICAL packages. Provenance becomes a useful companion signal there.

A CRITICAL package with provenance is a different risk than one without. Both have a single npm publisher controlling 100M+ weekly downloads. But with provenance, at least you know a compromised token can’t silently inject a different artifact. The published tarball has a verifiable build chain. That’s worth distinguishing.

The JSON output (via --json) now includes provenanceCount alongside criticalCount, so you can build custom gate logic in CI if you want to treat “CRITICAL with provenance” differently from “CRITICAL without.”


One signal, not a moat

Provenance doesn’t tell you whether the CI workflow itself is trustworthy. It doesn’t protect against a compromised GitHub runner or a malicious prepare hook. It doesn’t help with packages that don’t use GitHub Actions at all.

A package with provenance can still be a supply chain risk. A package without it can be well-maintained and safe. The column is a data point, not a verdict.

What it eliminates is the token-theft publish path. That’s a real attack vector (the axios compromise in March 2026 happened via stolen credentials), and Trusted Publishing closes it. That matters. It just doesn’t make the whole supply-chain problem go away.


Where this is heading

The current state of npm Trusted Publishing adoption is uneven. Axios has it. Chalk doesn’t. Many popular packages are somewhere in between. npm is pushing adoption via registry-side announcements, but there’s no enforcement.

The direction the ecosystem is moving: provenance as baseline, not differentiator. SLSA levels applied to package ecosystems. Software bills of materials as contractual requirements in regulated industries. In five years, a package without provenance may look like a package without a readme looks today.

The Provenance column in proof-of-commitment is there so you can see where your dependencies are on that curve, right now, without opening a browser.


proof-of-commitment v1.7.0 is on npm. Run npx proof-of-commitment [packages] against your own dependencies to see provenance coverage. If you’re a package maintainer and want to set up Trusted Publishing, the npm docs are clear and the setup takes about 10 minutes.

Stay in the loop

Early access, research updates, and the occasional strong opinion.