Skip to content

pnpr: verify tarball SHA on publish #11975

Description

@zkochan

Part of #11973.

Problem

registry/crates/pnpm-registry/src/publish.rs accepts incoming tarballs without verifying that their bytes hash to the integrity value the client claims in the packument. A search across that file for integrity, shasum, or hash turns up only a comment about time.modified formatting — no hashing of the payload itself.

That means:

  • A buggy or partial-upload client can land a tarball on disk whose content hash does not match dist.integrity / dist.shasum in the packument.
  • Downstream pnpm install will later fail with EINTEGRITY when fetching it — but by then the bad publish is already replicated to other clients/caches.
  • A malicious client can deliberately decouple the advertised hash from the actual bytes, depending on whether downstream consumers verify (most do; not all do under every flag combination).

This is a silent-corruption class bug. Cost grows linearly with publishes accumulated before it's fixed.

Scope

  • Hash the uploaded tarball as it streams in (SHA-512 for dist.integrity, SHA-1 for legacy dist.shasum).
  • Compare the computed digests against the values declared in the publish packument (packageJson.versions[v].dist.integrity and .shasum).
  • Reject the publish with a 400 + structured error if either digest doesn't match. Error code: EINTEGRITY (match what clients already understand).
  • Reject the publish if the dist.integrity field is missing entirely (today npm always sends it; mirror the tarball-shaped-lockfile change from f03dc2d in spirit).
  • Streaming, not buffer-the-whole-tarball-then-hash — for large publishes we shouldn't hold the full payload in memory just to check a hash.

Bonus (same PR, cheap once we're hashing)

  • Length check: verify Content-Length matches the byte count we actually read.

Acceptance

  • Integration test: publish a tarball whose declared dist.integrity doesn't match the bytes → 400 EINTEGRITY, no on-disk artifact written.
  • Integration test: publish without dist.integrity in the packument → 400 with a clear "integrity required" message.
  • Integration test: well-formed publish still succeeds; pnpm install against the resulting registry verifies the tarball end-to-end.

Related


Written by an agent (Claude Code, claude-opus-4-7).

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions