DevSecOps

npm provenance attestations walkthrough for 2026

npm provenance ties a published package to the specific GitHub Actions run that built it, signed through sigstore. Here is how to enable it for a publisher, verify it on the install side, and enforce it in CI without breaking your release process.

Hritik Sharma
Security Engineer
9 min read

npm's provenance attestation feature has matured from an interesting beta into something close to table stakes for serious open source packages, and 2026 is probably the year where any package that does not ship provenance should expect to be quietly downgraded in the trust models of careful downstream consumers. The mechanics are not complicated once you have seen them work; npm CLI in publish mode requests an OIDC token from the CI runner, exchanges it through sigstore's fulcio CA for a short-lived signing certificate tied to the runner's identity, signs an in-toto statement describing the build, uploads everything to the public sigstore transparency log, and includes a reference to the attestation in the published package metadata. The result is that a consumer can verify, days or years later, that a given tarball was produced by a specific GitHub Actions workflow run from a specific commit in a specific repository.

What makes the walkthrough worth doing is the gap between the headline claim and the actual operational state of provenance verification. Generating attestations is straightforward; verifying them is straightforward; enforcing them in a way that does not break your build the first time a transitive dependency forgets to publish with provenance is where most teams have to make decisions that are not obvious from the docs alone. This piece walks through the publisher side, the consumer side, and the enforcement side as they stand in 2026.

How do you actually enable provenance as a publisher?

The publisher requirements are narrow but specific. The package has to be published from a supported CI environment, which today means GitHub Actions and GitLab CI, with the publish job running in a workflow that has id-token: write permission so it can request the OIDC token sigstore needs. The publish step uses npm publish --provenance rather than a plain npm publish, and the npm CLI does the rest. Inside the CLI, the steps are: request the OIDC token from the GitHub Actions token endpoint, send it to npm's provenance service, which proxies through to sigstore's fulcio to mint a code signing certificate bound to the workflow identity, sign an SLSA-style in-toto statement that names the subject (the tarball digest), the builder (the workflow run URL), and the source materials (the commit SHA and repository URL), upload the bundle to the public sigstore Rekor transparency log, and attach the attestation to the package version when it lands on the registry.

The practical implications are that the source repository has to be public or the workflow has to have access to a private repo's contents, the workflow file itself is what binds the published artifact to a specific build, and any drift between the workflow that actually builds the package and the workflow that publishes it weakens the attestation. Most teams handle this by structuring the release workflow as a single job that builds and publishes in sequence, with the build artifact passed in memory rather than uploaded and re-downloaded between steps. Splitting the build and publish into separate jobs is possible but makes the attestation cover only the publish step, which is less useful for consumers who want to verify the build itself.

A small piece of operational hygiene that catches people: the npm token used in the publish step still has to exist and still has to have publish rights on the package. Provenance does not replace authentication; it adds a verifiable record of the build that produced the artifact. The token is what proves the workflow has permission to publish under the package name; the provenance attestation is what proves which workflow ran. Trusted Publishing changes the token side of this picture, but the provenance side is unchanged either way.

How do you verify provenance on the consumer side?

The npm CLI exposes provenance verification through npm audit signatures, which fetches the attestation bundles for each installed package, walks the sigstore certificate chain, verifies the in-toto statement against the tarball digest, and checks that the attestation is present in the Rekor transparency log. The command runs against an existing node_modules tree or against a lockfile, and it produces a summary of which packages had verifiable provenance, which had signatures but no provenance, and which had nothing at all. For a fresh install in 2026, the proportion of packages with provenance varies wildly by ecosystem; high-profile packages from major maintainers nearly all have it, and the long tail still has substantial gaps.

The mechanics of what npm audit signatures is actually doing are worth understanding because the verification has more moving parts than a typical signature check. The sigstore certificate chain has to be valid against the Fulcio root that npm trusts, the in-toto statement has to match the tarball you actually downloaded, the Rekor log entry has to be consistent with the certificate and the statement, the workflow identity in the certificate has to match the repository the package metadata claims to come from, and the source repository URL in the in-toto statement has to be consistent with the package's repository field. Any one of these can fail, and a careful consumer wants to know which one when they do.

For higher-value verification, the recommendation in 2026 is to pin trust to specific publisher identities rather than to accept any provenance from any source. A package whose attestation shows it was built by org/repo on the main branch with a tag matching the package version is meaningfully more trustworthy than a package whose attestation points at an arbitrary workflow in a fork. The sigstore identity model supports this kind of pinning, and the tooling around it is improving; cosign verify-attestation and similar tools have been gaining options to filter on workflow identity, branch, and trigger event.

How do you enforce provenance in CI without breaking your build?

The honest enforcement strategy in 2026 is staged. A hard requirement that every dependency must have provenance, including transitives, will not pass a real npm install for any non-trivial application because the long tail of dependencies still has gaps. The realistic posture is to run npm audit signatures in CI, capture the report, fail the build on signature verification errors (which indicate tampering or registry compromise), and treat missing provenance as a warning that surfaces in dashboards rather than as a build-breaking gate.

The next step up is to define a critical-package list where provenance is required, and to enforce that requirement at install time using a wrapper around npm install or a custom resolver. The list typically includes the packages whose compromise would be catastrophic: build tooling, popular utility libraries with millions of weekly downloads, anything in the React or TypeScript core ecosystem, and anything that runs in your application's hot path. For these packages, missing or invalid provenance is a hard fail; for the rest of the tree, the report goes to the security team for review.

The enforcement that does generalize is signature verification, which has been the default expectation for npm packages since long before provenance existed. Every package on the registry is signed by npm's registry signing key, and npm audit signatures verifies these signatures as part of the same flow. Signature verification failures are rare and almost always indicate that something has gone wrong between the registry and the consumer, and a CI gate that fails on signature errors does not produce false positives in normal operation. Pairing signature enforcement with provenance reporting gives you the strong guarantee where it exists and visibility into the weaker guarantee everywhere else.

What are the limits of provenance, and what does it not protect against?

Provenance proves that a specific workflow run produced a specific tarball; it does not prove that the workflow run was honest about its inputs or that the workflow itself was not compromised. A maintainer whose GitHub Actions runner has been tampered with, or whose workflow file pulls in a malicious action through uses: org/action@main, can produce a provenance attestation for a malicious package that looks pristine on inspection. The tj-actions/changed-files compromise in 2025 is a clean example of how an attestation can be technically correct while the underlying build was being manipulated.

Provenance also does not say anything about the quality or behavior of the code inside the package. A package can have an attestation that ties it to a specific commit, and the commit can contain a backdoor that the maintainer added intentionally. Verifying provenance does not replace dependency review, behavioral analysis, or any of the other layers that a serious supply chain program runs; it adds one more layer that closes off a specific attack pattern (the registry-side tampering or impersonation case) without claiming to address the rest of the stack.

The other limit worth naming is that provenance is currently an opt-in feature, and a package that did not publish with provenance does not produce a verification failure; npm audit signatures simply reports that no attestation is available. The signal-to-noise on missing provenance varies, and treating its absence as a hard fail breaks too many real installs to be practical in 2026. The right framing is that provenance is a positive trust signal where present, not a definitive verdict where absent.

How Safeguard Helps

Safeguard ingests sigstore-backed provenance attestations for every npm package we see and surfaces them inside the same SBOM and dependency views as the rest of your supply chain data. Griffin AI compares each attestation's workflow identity, source repository, and commit against the package's stated repository and against historical attestations from the same publisher, so a sudden change in builder identity or branch shows up as a flagged event rather than buried in a verification log. Reachability analysis tells you which unattested dependencies are actually called by your application versus which ones are inert, so the long tail of packages without provenance can be prioritized by real exposure rather than by alphabetical order. TPRM workflows let you require provenance for vendor-supplied packages and track the gap closing over time, and policy gates enforce critical-package provenance requirements in CI without breaking on the rest of the tree. The result is provenance as a continuously verified property of your dependency graph, not just a one-shot check in a single CI job.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.