Checking Build Provenance Across npm, PyPI, and crates.io
Description and use
Checking build provenance in npm, PyPI, and crates.io: npm publishes attestations in 52 % of cases, PyPI in 85 % via a hidden endpoint, and crates.io does not expose provenance in its sparse index.
Problem
Determining whether a package release was built by an automated CI pipeline or manually uploaded from a laptop, using registry-provided provenance data.
Outcome
npm exposes provenance in 52% of tested packages, PyPI in 85% via a hidden endpoint, and crates.io does not expose provenance in its sparse index. The study highlights inconsistencies across registries and the need for a unified provenance column.
Workflow
- 1. Query npm registry JSON for a package and check for the "attestations" key.
- 2. If present, follow the provided URL to retrieve the Sigstore DSSE bundle and verify the Rekor transparency log entry.
- 3. For PyPI, send a request to the simple API endpoint with "Accept: application/vnd.pypi.simple.v1+json" and inspect the "provenance" field in the returned file metadata.
- 4. For crates.io, fetch the sparse index file for a crate and note that no provenance fields are present.
- 5. Record the presence or absence of provenance data for each package in a normalized column.
- 6. Use this data to inform downstream security checks or CI gates.
Evidence
I ran that check against 25 well-known packages. 13 of them (52%) have it: react, vite, esbuild, turbo, zod, @actions/core, semver.
Across 20 packages, 17 (85%) had this — noticeably higher adoption than npm's 52% in my sample.
Trusted Publishing verifies identity at the moment of cargo publish — but that verification doesn't leave a mark anywhere a downstream tool can later read.
- Record date: 2026-09-19T23:45:35.033Z