skip to content

Who actually verifies npm provenance or PyPI attestations, and at what point in the flow?

level: middleimportance: should knowfreq 44%

answer

  1. three checkpoints, one automatic
  2. registries verify at upload, not install
  3. install commands check nothing by default
  4. opt-in check, after the fact
  5. registry signature is not provenance

basics

~20 s

Mostly the registry, at upload time. A normal npm install or pip install verifies nothing. Consumers have to opt in: npm audit signatures checks an installed tree, and PyPI attestations must be fetched and checked deliberately.

solid answer

~50 s

There are three checkpoints and only one runs by itself. **At publish**, the registry validates the trust material it receives — PyPI checks that an uploaded attestation's Sigstore identity matches the project's configured trusted publisher and that the subject digest matches the file. That protects the index, not you. **At install**, nothing happens: `npm install` and `pip install` resolve, download and unpack without checking any attestation. **The third checkpoint is deliberate consumer-side verification**, and it is the one teams skip. On npm that is `npm audit signatures`, which validates the registry's own signatures over package metadata and any provenance attestations across the resolved tree. On PyPI you fetch the published provenance and verify it yourself. The whole leaf of this topic lives in that gap: publishing trust material and acting on it are different projects, and almost every ecosystem has done the first and not the second.

go deeper

for a junior

Remember the blunt fact: installing a package does not check its provenance. The badge on a registry page has no effect on your build unless someone wired up a check.

for a middle

Lay out the three checkpoints — upload, install, deliberate consumer check — and say who each protects. Distinguish a registry signature over metadata from a build-origin attestation.

for a senior

Talk about where you would put the check in a real estate: on ingest at the internal proxy, recorded, rather than hoping every team runs it. Explain why a lossy mirror is a silent control failure.

for a principal

Own the sentence "signing without verification changes nothing", and be ready to say what you would fund first when the publishing half is done and the consuming half is not.

## Three checkpoints, and which of them protects you ### 1. Upload time — the registry checks When a publisher uploads, the registry validates the trust material before accepting it. On PyPI, attestations are tied to trusted publishing: an uploaded attestation is checked so that the Sigstore identity it carries matches the publisher configured for that project, and the statement's subject digest matches the distribution file actually being uploaded. On npm, a provenance attestation is generated during a publish that runs under a recognised CI identity, and the registry stores it beside the package. This is real verification and it does real work — it stops a publisher from attaching an attestation that describes a different file, or one signed by an unrelated identity. But be precise about who it protects: **the registry is protecting the integrity of its own index.** It tells a downstream consumer nothing about whether the artifact that eventually landed in their `node_modules` or site-packages is that same artifact. ### 2. Install time — nothing happens This is the answer people get wrong. `npm install` resolves the dependency graph, downloads tarballs, checks the lockfile's integrity hashes if there is a lockfile, and unpacks. It does not evaluate provenance. `pip install` downloads and installs a wheel; it does not verify PEP 740 attestations. Neither will fail because a package lacks an attestation, and neither will fail because an attestation names a repository you have never heard of. So a package's shiny provenance badge on a registry web page has, by default, zero effect on any build in your organisation. ### 3. Consumer-side verification — opt in, or nothing On npm, `npm audit signatures` is the built-in consumer check. It walks the installed tree and reports on two distinct things: - **Registry signatures** — the registry's own signature over package metadata, asserting that the tarball you received matches what the registry holds. This defends the path *from registry to you*. - **Provenance attestations** — where present, the build-origin claim. This defends the path *from source to registry*. Those are different claims and passing one is not passing the other. Candidates who conflate them are missing half the picture: the registry signature says nothing about who built the code, and the provenance says nothing about whether your proxy swapped the bytes on the way down. On PyPI, the published attestation material is retrievable and verifiable, but it is a step you take on purpose, in a pipeline you wrote. There is no default install-time gate. ## Why the gap exists Publishing side effort is small and concentrated: a flag, a CI change, one maintainer. Consuming side effort is diffuse: every team, every build, in an ecosystem where most packages carry nothing, and where a hard gate breaks builds on day one. So ecosystems shipped the publishing half first and the consuming half is still catching up. That asymmetry is the honest answer to "is supply chain signing solved" — and it is why *signing without verification changes nothing* is the sentence to have ready. ## The failure mode nobody sees coming: a lossy mirror Enterprises rarely install straight from a public registry. They install through an internal proxy or mirror. If that proxy rehosts only the tarball or wheel and does not carry the attestation bundle, then the trust material exists upstream and is simply unavailable inside the company. Nothing errors. The consumer-side check reports **"no attestation"** — which reads identically to a package that never published one. That is a control failure inside your own estate, and it has two fixes: verify at the boundary (check on ingest into the mirror, record the result, and refuse to promote artifacts that fail) or make the mirror preserve and serve the trust material so downstream checks still work. The first is usually more practical, because it puts the check at the one place where you can guarantee it runs. ## Reading a failed check A verification failure is not automatically an incident. Common mundane causes: the package predates registry signing, a mirror stripped the metadata, or a package was resolved from a source that does not sign at all. Triage it. But there is one result that always warrants stopping the line: a signature or digest that is *present and does not match the bytes you have*. Absence is a coverage problem; mismatch is an integrity problem, and collapsing the two into one alert level is how teams learn to ignore both.

  • What is the difference between npm's registry signature and a provenance attestation?
    The registry signature is npm's own signature over package metadata: it says the tarball you received is the one the registry holds. Provenance says where that tarball came from — repository, commit, workflow. The first defends the path from registry to you, the second the path from source to registry. `npm audit signatures` reports on both, and passing one is not passing the other.
  • Your company installs everything through an internal mirror that rehosts only the wheel. What breaks?
    Verification, silently. If the proxy does not carry the attestation bundle alongside the artifact, nobody inside the company can check anything, and the check reports "no attestation" rather than an error — indistinguishable from a package that never published one. Fix it by verifying on ingest into the mirror and recording the result, or by making the mirror preserve and serve the trust material.
  • `npm audit signatures` fails on one package. Is that a security incident?
    Not necessarily. Mundane causes dominate: the package predates registry signing, a mirror stripped metadata, or it came from a source that does not sign. Treat that as a coverage problem needing triage. But a signature or digest that is present and does not match the bytes you actually have is an integrity problem, and that one stops the line.

saying these in an interview costs you the question

  • Assumes npm install verifies provenance automatically
  • Thinks pip verifies attestations at install time
  • Treats registry-side upload checks as consumer protection
  • Conflates the registry signature with build provenance
  • Says a missing attestation and a bad one are the same result

context