Back to publishing & release Automate semantic versioning Publish to the npm registry Harden the supply chain

Verifying npm Package Provenance Before You Depend on It

You want assurance that a dependency's published tarball actually came from its claimed source repository and CI, not a hijacked account. This page shows how to check npm provenance attestations before trusting a package.

Exact symptoms and error messages

Exact symptoms and error messages Exact symptoms and error messages in production JavaScript package workflows. Exact symptoms and error messages Exact symptoms and error messages in production JavaScript package workflows.
Exact symptoms and error messages — the core idea of this section at a glance.
# a package with no provenance gives you no build-origin guarantee
$ npm view some-lib dist.attestations
undefined

Root cause analysis

Provenance is a signed attestation, generated by CI via OIDC, that ties a published tarball to a specific source commit and build. A package without it offers no cryptographic link between the code on GitHub and the tarball on the registry, so an account compromise can publish anything. Verifying provenance is the consumer side of the publisher defenses in Supply-Chain Security Hardening and Adding SLSA Provenance to Package Releases.

Root cause analysis Provenance is a signed attestation, generated by CI via OIDC, that ties a published tarball to a specific source commit Root cause analysis Provenance is a signed attestation, generated by CI via OIDC, that ties a published tarball to a specific source commit and build.
Root cause analysis — the core idea of this section at a glance.

Provenance is a signed attestation generated by CI via OIDC that binds a published tarball to a specific source commit and build workflow. Without it, there is no cryptographic link between the code you can read on GitHub and the tarball the registry serves — so a compromised maintainer account, or a registry-side tampering, can publish anything under a trusted name and you have no way to detect it. Verifying provenance is how a consumer regains that link.

What provenance does not prove is that the code is benign. It confirms origin and integrity — this tarball really came from that source and build, unmodified — not intent. A malicious-but-authentic author can still publish signed, provenance-backed malware. Provenance defends against account hijacks and supply-chain tampering, which is a large and important class of attack, but it is one layer among several rather than a guarantee of safety.

Provenance is a signed attestation, generated by CI via OIDC, that binds a published tarball to a specific source commit and build workflow. A package without it offers no cryptographic link between the code you can read on its source host and the tarball the registry serves, so a compromised maintainer account or registry-side tampering can publish anything under a trusted name and you have no way to detect it. Verifying provenance is how a consumer regains that link and gains assurance about where a package actually came from.

What provenance does not prove is that the code is benign. It confirms origin and integrity — this tarball really came from that source and build, unmodified — not intent, so a malicious-but-authentic author can still publish signed, provenance-backed malware. Provenance therefore defends against a specific and important class of attack: account hijacks and supply-chain tampering. It is one layer of a broader posture rather than a guarantee of safety, which is why it is paired with audit thresholds, host allow-listing, and script blocking.

Resolution and configuration patch

Check for and verify attestations before adopting a dependency:

Resolution and configuration patch Check for and verify attestations before adopting a dependency: Resolution and configuration patch Check for and verify attestations before adopting a dependency:
Resolution and configuration patch — the core idea of this section at a glance.
# Does the package publish provenance?
npm view some-lib dist.attestations
# Verify the signed attestations for what you have installed
npm audit signatures

Prefer dependencies that publish provenance, and treat a missing attestation on a security-critical package as a reason to pin and review.

Check for and verify attestations before depending on a package, and enforce verification in CI:

# Does the package publish provenance?
npm view some-lib dist.attestations
# Verify signatures and provenance across the installed tree
npm audit signatures

Running npm audit signatures in CI fails the build when a package that should carry provenance does not verify, turning verification into an enforced gate rather than a manual spot-check. Prefer dependencies that publish provenance for security-critical code, and treat a missing attestation on such a package as a reason to pin the version and review before adopting.

CLI validation and debug commands

CLI validation and debug commands CLI validation and debug commands in production JavaScript package workflows. CLI validation and debug commands CLI validation and debug commands in production JavaScript package workflows.
CLI validation and debug commands — the core idea of this section at a glance.
# Verify signatures/attestations across the installed tree
npm audit signatures
# Inspect the provenance's source repo and commit
npm view some-lib --json | jq '.dist.attestations'

Prevention and CI guardrails

  • Prefer dependencies that publish provenance for security-critical code.
  • Run npm audit signatures in CI to verify attestations on install.
  • Pin and review packages that lack provenance before depending on them.
  • Publish provenance for your own packages so consumers can verify you in turn.
Prevention and CI guardrails Prevention and CI guardrails in production JavaScript package workflows. Prevention and CI guardrails Prevention and CI guardrails in production JavaScript package workflows.
Prevention and CI guardrails — the core idea of this section at a glance.
  • Prefer dependencies that publish provenance for security-critical code.
  • Run npm audit signatures in CI to verify attestations on every install.
  • Pin and review packages that lack provenance before depending on them.
  • Publish provenance for your own packages so consumers can verify you in turn.

Verifying attestations across your dependency tree

Checking one package by hand does not scale; the practical move is to verify signatures and attestations across everything you have installed, as a CI step. npm audit signatures walks the installed tree and verifies registry signatures and provenance attestations, failing when verification does not hold.

Tree-wide verify audit signatures verifies the whole installed tree in CI. npm audit signatures walk the tree verify each signature + provenance fail on mismatch block install
Verifying attestations as a CI gate catches a broken signature before it ships.
# Verify registry signatures and provenance for the whole tree
npm audit signatures

Run it in CI so a package that loses its expected signature — or whose attestation does not verify — fails the build rather than shipping silently. For security-critical dependencies specifically, prefer ones that publish provenance, and treat a missing attestation on such a package as a reason to pin the version and review before adopting. The goal is to make provenance verification a routine gate, not a manual spot-check you do once and forget.

Publishing your own provenance

Verification has a mirror obligation: publish provenance for your own packages so your consumers can verify you in turn. With OIDC-based publishing from CI, the registry attaches an attestation tying your tarball to its source and build, and consumers running npm audit signatures see it verified.

Publish provenance OIDC-signed attestation ties your tarball to its build. id-token: write OIDC identity npm publish --provenance signed attestation consumers verify chain of trust
Publishing provenance lets your consumers verify you as you verify your deps.
    permissions:
      id-token: write
    steps:
      - run: npm publish --provenance

Granting the workflow id-token: write and publishing with --provenance is usually the whole change — and it doubles as the token-free publishing path, since the OIDC identity replaces a standing token. Publishing provenance is how you participate in the same chain of trust you rely on when consuming: you verify your dependencies, and you give your consumers the means to verify you, which is what makes the ecosystem-wide guarantee actually hold.

Verifying provenance across the whole tree

Checking one package by hand does not scale, so the practical approach is to verify signatures and attestations across everything installed, as a CI step. npm audit signatures walks the installed dependency tree and verifies registry signatures and provenance attestations, failing when a package that should carry provenance does not verify or when a signature does not match. Running it in CI turns provenance from a badge nobody checks into an enforced property: a dependency that loses its expected signature, or whose attestation does not match its claimed source, fails the build rather than shipping silently.

Tree-wide verify audit signatures verifies the installed tree in CI. npm audit signatures walk the tree verify each signature + provenance fail on mismatch enforced gate
Verifying attestations as a CI gate catches a broken or missing signature before it ships.

For security-critical dependencies specifically, the verification is worth pairing with a policy of preferring packages that publish provenance and treating a missing attestation as a signal to pin and review. Provenance coverage across the ecosystem is growing, so a security-important package that does not publish it is increasingly an outlier worth scrutinizing. Making npm audit signatures a routine gate, rather than a one-time manual check, is what keeps the assurance current as your dependency tree changes — every new or updated dependency is verified on the next CI run, so a package that quietly loses its provenance or fails verification is caught immediately.

Publishing your own provenance to complete the chain

Verification has a mirror obligation: publishing provenance for your own packages so your consumers can verify you in turn. With OIDC-based publishing from CI, the registry attaches an attestation tying your tarball to its source and build, and consumers running npm audit signatures see it verified. Granting the workflow id-token: write and publishing with --provenance is usually the entire change, and it doubles as the token-free publishing path since the OIDC identity replaces a standing token.

Complete the chain Publish provenance so consumers can verify you. id-token: write OIDC identity publish --provenance signed attestation consumers verify chain of trust
Publishing provenance is the counterpart to relying on it — a shared verification fabric.

Participating in the chain of trust as both a consumer and a publisher is what makes the ecosystem-wide guarantee actually hold. You verify your dependencies' provenance, and you give your consumers the means to verify yours; the more packages that do both, the harder it becomes for a hijacked account or a tampered publish to go undetected anywhere in the graph. Provenance is not a feature you adopt purely for your own protection — it is a contribution to a shared verification fabric, and publishing it is the natural counterpart to relying on it when you install.

Where provenance fits in a layered defense

Provenance verification is one control in a layered supply-chain defense, and understanding what each layer covers clarifies why no single one suffices. Blocking install scripts stops arbitrary install-time code execution; an audit threshold catches known-vulnerable versions; host allow-listing with lockfile-lint blocks resolution from an untrusted registry; and provenance verification confirms a package came from its claimed source and build. Each addresses a distinct attack surface, so a package could pass three checks and fail the fourth — audited-clean but tampered, or script-free but from a malicious host.

Layered defense Provenance is the origin layer among four. --ignore-scripts install-time code audit threshold known CVEs lockfile-lint resolution hosts provenance verified origin
Each layer covers a distinct surface — stack them so an attacker must defeat all.

Stacking them means an attacker must defeat every layer rather than any single one. A CI security gate that runs a frozen install with ignored scripts, a thresholded audit, a host allow-list check, and npm audit signatures for provenance measures every push against the whole posture, and each check is fast and deterministic. Provenance's specific contribution is the origin dimension: it is the layer that catches a hijacked account or a tampered publish, which the vulnerability, host, and script checks do not address. Placing it alongside the others — rather than treating any one as sufficient — is what turns a collection of individual controls into genuine defense in depth for the dependency graph.

Frequently Asked Questions

Does provenance prove the code is safe?

No — it proves the tarball came from the claimed source and CI build, not that the code is benign. It defends against account hijacks and tampering, not against a malicious-but-authentic author.

How do I verify provenance in CI?

Run npm audit signatures, which verifies registry signatures and provenance attestations for your installed packages, and fail the job if verification fails on a package you require.

Does provenance prove a package is safe?

No — it proves the tarball came from the claimed source and build, unmodified. It defends against account hijacks and tampering, not against a malicious-but-authentic author. Treat it as one layer of defense, not a safety guarantee.

How do I verify provenance across all my dependencies?

Run npm audit signatures in CI. It walks the installed tree and verifies registry signatures and provenance attestations, failing the build when verification does not hold — a routine gate rather than a manual spot-check.

How do I publish provenance for my own package?

Publish from CI with id-token: write permission and npm publish --provenance. The registry attaches an attestation tying the tarball to its source and build, which also removes the need for a standing publish token.

Does provenance prove a package is safe?

No — it proves the tarball came from the claimed source and build, unmodified. It defends against account hijacks and tampering, not against a malicious-but-authentic author. Treat it as one layer of a supply-chain posture alongside audit thresholds, host allow-listing, and script blocking.

How do I verify provenance across all my dependencies?

Run npm audit signatures in CI. It walks the installed tree and verifies registry signatures and provenance attestations, failing the build when a package that should carry provenance does not verify — a routine, enforced gate rather than a manual spot-check.

How do I publish provenance for my own package?

Publish from CI with id-token: write permission and npm publish --provenance. The registry attaches an attestation tying the tarball to its source and build, which also removes the need for a standing publish token.

Where does provenance fit alongside my other supply-chain checks?

It is the origin layer. Script blocking covers install-time code, an audit threshold covers known vulnerabilities, lockfile-lint covers resolution hosts, and provenance covers where the package came from — catching a hijacked account or tampered publish the others miss. Run all four in one CI gate for defense in depth.

Do all npm packages publish provenance?

Not yet — coverage is growing but far from universal. For security-critical dependencies, prefer ones that publish provenance and treat a missing attestation as a reason to pin and review, while running npm audit signatures to verify the ones that do.

Related

Supply-Chain Security Hardening