fix: require integrity for tarball-shaped lockfile resolutions (backport #11966 to v10)#12007
Conversation
…ort #11966 to v10) A tampered `pnpm-lock.yaml` that strips the `integrity` field from a tarball resolution let the worker download the URL contents and mint a fresh integrity from the unverified bytes. An attacker who could both alter the lockfile (e.g. via a pull request that drops `integrity:`) and serve modified content at the referenced tarball URL could install a tampered package without any error — including under `--frozen-lockfile`. `pkgSnapshotToResolution` now fails closed at lockfile-read time with `ERR_PNPM_MISSING_TARBALL_INTEGRITY` whenever a tarball-shaped resolution (no `type` field — covers plain remote, registry-derived, `file:`, and `gitHosted` entries) lacks integrity. Git-hosted tarballs and `file:` tarballs remain exempt: the commit SHA in a git-host URL and the user-controlled local path already anchor the bytes. The fix sits at the lockfile-read chokepoint every install path flows through (deps-resolver, deps-restorer, graph-builder), so both isolated and hoisted node-linkers are covered. Credit to AutoFyn for finding and reporting the issue.
|
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: Organization UI 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)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Review Summary by QodoRequire integrity field for remote tarball lockfile resolutions
WalkthroughsDescription• Prevent installation of tampered tarballs by requiring integrity field • Add validation in pkgSnapshotToResolution to fail at lockfile-read time • Exempt git-hosted and file: tarballs from integrity requirement • Add helper function to detect git-hosted tarball URLs for legacy lockfiles Diagramflowchart LR
A["Lockfile Read"] --> B["pkgSnapshotToResolution"]
B --> C{"Tarball Resolution?"}
C -->|"No type field"| D{"Has integrity?"}
D -->|"No"| E{"Git-hosted or file:?"}
E -->|"Yes"| F["Allow"]
E -->|"No"| G["Throw ERR_PNPM_MISSING_TARBALL_INTEGRITY"]
D -->|"Yes"| F
C -->|"Has type field"| F
File Changes1. lockfile/utils/src/pkgSnapshotToResolution.ts
|
Summary
Backport of #11966 to
release/10.A tampered
pnpm-lock.yamlthat strips theintegrityfield from a tarball resolution let the worker download the URL contents and mint a fresh integrity from the unverified bytes. An attacker who could both alter the lockfile (e.g. via a pull request that dropsintegrity:) and serve modified content at the referenced tarball URL could install a tampered package without any error — including under--frozen-lockfile.pkgSnapshotToResolutionnow fails closed at lockfile-read time withERR_PNPM_MISSING_TARBALL_INTEGRITYwhenever a tarball-shaped resolution (notypefield — covers plain remote, registry-derived,file:, andgitHostedentries) lacks integrity. Git-hosted tarballs (gitHosted: trueor a URL on codeload.github.com / bitbucket.org / gitlab.com) andfile:tarballs are exempt — the commit SHA in a git-host URL and the user-controlled local path already anchor the bytes.The fix sits at the lockfile-read chokepoint every install path flows through (
deps-resolver,deps-restorer,graph-builder), so both isolated and hoisted node-linkers are covered. The worker's ownif (integrity)mint path is intentionally left in place because it is still the legitimate fresh-install code path for resolutions that have not yet been recorded in a lockfile (the resolver attaches the computed integrity back to the resolution before the lockfile write).I scanned every
pnpm-lock.yamlfixture in the repo for tarball entries without integrity — there are none, so no existing test breaks from the stricter check.Credit to AutoFyn for finding and reporting the issue.
Backport notes
The v10 branch does not yet have
lockfile/utils/src/toLockfileResolution.ts, so theisGitHostedTarballUrlhelper is inlined as a private function insidepkgSnapshotToResolution.tsrather than exported from a sibling module.@pnpm/erroris added as a new direct dependency of@pnpm/lockfile.utils. Pacquet changes from the original PR don't apply to v10.Test plan
lockfile/utils/test/pkgSnapshotToResolution.tsassert the throw fires for plain remote and CDN tarball entries that lack integrity, and that git-hosted (flag + URL fallback) andfile:tarballs remain exempt.pnpm --filter @pnpm/lockfile.utils run lintclean.pnpm --filter @pnpm/lockfile.utils testpasses (4/4 tests).pnpm-lock.yamlfiles in the repo — no tarball entries lack integrity, so no existing fixture breaks.Written by an agent (Claude Code, claude-opus-4-7).