Skip to content

fix: pin integrity of git-hosted tarballs in lockfile (v10 backport)#11491

Merged
zkochan merged 1 commit into
release/10from
cherry-git-tarball-integrity-v10
May 6, 2026
Merged

fix: pin integrity of git-hosted tarballs in lockfile (v10 backport)#11491
zkochan merged 1 commit into
release/10from
cherry-git-tarball-integrity-v10

Conversation

@zkochan

@zkochan zkochan commented May 6, 2026

Copy link
Copy Markdown
Member

Summary

Cherry-pick of #11481 from main to release/10, adapted to the v10 layout.

For git-hosted tarballs (codeload.github.com / gitlab.com / bitbucket.org) the fetcher dropped the integrity it computed while downloading, so the lockfile only stored the URL. A compromised git host or man-in-the-middle could serve a substituted tarball on subsequent installs and pnpm would install it without lockfile changes.

This pins the SHA-512 SRI of the raw tarball in the lockfile in the same sha512-<base64> form npm-registry tarballs use; subsequent installs verify the download against that integrity in the worker (addTarballToStoreparseIntegrity → hash compare), so a tampered tarball fails with TarballIntegrityError.

Why git-hosted stays on the per-package store path

The lockfile pins integrity for security, but the store key for git-hosted resolutions stays on the per-package path (<storeDir>/<targetRelative>/integrity.json) rather than collapsing under the integrity-based cafs key. Reason: git-hosted tarballs are post-processed (preparePackage / packlist), so the cached file set depends on whether build scripts ran during fetch. The integrity-only key would fold the built and not-built variants into a single slot, letting one overwrite the other if ignoreScripts was toggled between runs. The integrity is still validated on every fresh download.

How the routing stays clean

A new optional gitHosted: boolean field on TarballResolution:

  • The git resolver sets it on every git-hosted tarball it produces.
  • The lockfile loader (convertToLockfileObject) backfills it on load for older lockfiles via inlined URL detection.
  • Every consumer reads resolution.gitHosted directly. URL detection lives in exactly two places — the resolver and the loader — instead of scattered across each call site.

v10-specific adaptations

  • v10 has no installing/deps-installer or building/after-install directories — those changes folded into pkg-manager/resolve-dependencies/updateLockfile.ts (which has its own inline toLockfileResolution) and exec/plugin-commands-rebuild.
  • v10's lockfile/utils had no separate toLockfileResolution.ts/test; only pkgSnapshotToResolution.ts needed the gitHosted switch, plus its dependency on @pnpm/pick-fetcher was dropped (matching upstream's intent to keep URL detection inlined where it lives).
  • modules-mounter/daemon/createFuseHandlers.ts was left alone; git-hosted packages were already unsupported there before (no integrity → ssri.parse(undefined) would throw).
  • reviewing/license-scanner/getPkgInfo.ts got an extra fix beyond upstream: with the security change, 'integrity' in packageResolution is now true for git-hosted, so the per-package-path branch had to gate on gitHosted first.

Test plan

  • pnpm run compile — passes across all 199 packages
  • @pnpm/lockfile.fs unit tests (26)
  • @pnpm/lockfile.utils unit tests (2)
  • @pnpm/pick-fetcher unit tests (6)
  • @pnpm/resolve-dependencies unit tests (38)
  • @pnpm/package-requester tests (21)
  • @pnpm/git-resolver tests (71 — assert gitHosted: true on produced resolutions)
  • @pnpm/tarball-fetcher git-hosted tests — both the existing test (now asserts integrity is returned) and the new mismatched-integrity test (asserts TarballIntegrityError)
  • @pnpm/core fromRepo.ts "re-adding a git repo with a different tag" — lockfile snapshot updated for pinned integrity + gitHosted: true

🤖 Cherry-picked by Claude (claude-opus-4-7) on behalf of @zkochan

Cherry-pick of #11481 from main, adapted to the v10 layout.

For git-hosted tarballs (codeload.github.com / gitlab.com / bitbucket.org)
the fetcher dropped the integrity it computed while downloading, so the
lockfile only stored the URL. A compromised git host or man-in-the-middle
could serve a substituted tarball on subsequent installs and pnpm would
install it without lockfile changes.

This pins the SHA-512 SRI of the raw tarball in the lockfile in the same
sha512-<base64> form npm-registry tarballs use; subsequent installs verify
the download against that integrity in the worker.

A new optional gitHosted: boolean field is recorded on TarballResolution
so every store-key consumer can route by a single typed read instead of
re-deriving the routing from the URL. Lockfiles written by older pnpm
versions are enriched on load (URL fallback) so the field can be relied
on uniformly.

🤖 Cherry-picked by Claude (claude-opus-4-7) on behalf of @zkochan
@coderabbitai

coderabbitai Bot commented May 6, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: da8bb937-865e-43b6-820c-ac579c4be0f0

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cherry-git-tarball-integrity-v10

Comment @coderabbitai help to get the list of available commands and usage tips.

@zkochan zkochan merged commit edbe2a7 into release/10 May 6, 2026
11 of 14 checks passed
@zkochan zkochan deleted the cherry-git-tarball-integrity-v10 branch May 6, 2026 12:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant