fix: pin integrity of git-hosted tarballs in lockfile (v10 backport)#11491
Merged
Conversation
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
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Cherry-pick of #11481 from
maintorelease/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 (addTarballToStore→parseIntegrity→ hash compare), so a tampered tarball fails withTarballIntegrityError.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 ifignoreScriptswas toggled between runs. The integrity is still validated on every fresh download.How the routing stays clean
A new optional
gitHosted: booleanfield onTarballResolution:convertToLockfileObject) backfills it on load for older lockfiles via inlined URL detection.resolution.gitHosteddirectly. URL detection lives in exactly two places — the resolver and the loader — instead of scattered across each call site.v10-specific adaptations
installing/deps-installerorbuilding/after-installdirectories — those changes folded intopkg-manager/resolve-dependencies/updateLockfile.ts(which has its own inlinetoLockfileResolution) andexec/plugin-commands-rebuild.lockfile/utilshad no separatetoLockfileResolution.ts/test; onlypkgSnapshotToResolution.tsneeded thegitHostedswitch, plus its dependency on@pnpm/pick-fetcherwas dropped (matching upstream's intent to keep URL detection inlined where it lives).modules-mounter/daemon/createFuseHandlers.tswas left alone; git-hosted packages were already unsupported there before (no integrity →ssri.parse(undefined)would throw).reviewing/license-scanner/getPkgInfo.tsgot an extra fix beyond upstream: with the security change,'integrity' in packageResolutionis now true for git-hosted, so the per-package-path branch had to gate ongitHostedfirst.Test plan
pnpm run compile— passes across all 199 packages@pnpm/lockfile.fsunit tests (26)@pnpm/lockfile.utilsunit tests (2)@pnpm/pick-fetcherunit tests (6)@pnpm/resolve-dependenciesunit tests (38)@pnpm/package-requestertests (21)@pnpm/git-resolvertests (71 — assertgitHosted: trueon produced resolutions)@pnpm/tarball-fetchergit-hosted tests — both the existing test (now asserts integrity is returned) and the new mismatched-integrity test (assertsTarballIntegrityError)@pnpm/corefromRepo.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