Skip to content

fix: require integrity for tarball-shaped lockfile resolutions (backport #11966 to v10)#12007

Merged
zkochan merged 1 commit into
release/10from
backport-11966-v10
May 27, 2026
Merged

fix: require integrity for tarball-shaped lockfile resolutions (backport #11966 to v10)#12007
zkochan merged 1 commit into
release/10from
backport-11966-v10

Conversation

@zkochan

@zkochan zkochan commented May 27, 2026

Copy link
Copy Markdown
Member

Summary

Backport of #11966 to release/10.

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 (gitHosted: true or a URL on codeload.github.com / bitbucket.org / gitlab.com) and file: 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 own if (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.yaml fixture 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 the isGitHostedTarballUrl helper is inlined as a private function inside pkgSnapshotToResolution.ts rather than exported from a sibling module. @pnpm/error is added as a new direct dependency of @pnpm/lockfile.utils. Pacquet changes from the original PR don't apply to v10.

Test plan

  • New unit tests in lockfile/utils/test/pkgSnapshotToResolution.ts assert the throw fires for plain remote and CDN tarball entries that lack integrity, and that git-hosted (flag + URL fallback) and file: tarballs remain exempt.
  • The existing cdn.sheetjs.com test case is updated to carry integrity (it now represents the realistic lockfile state).
  • pnpm --filter @pnpm/lockfile.utils run lint clean.
  • pnpm --filter @pnpm/lockfile.utils test passes (4/4 tests).
  • Scanned all 99 pnpm-lock.yaml files in the repo — no tarball entries lack integrity, so no existing fixture breaks.

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

…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.
@coderabbitai

coderabbitai Bot commented May 27, 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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 3343cdd9-bd5d-4a98-bbda-30cc2efd273d

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 backport-11966-v10

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.

❤️ Share

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

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Review Summary by Qodo

Require integrity field for remote tarball lockfile resolutions

🐞 Bug fix

Grey Divider

Walkthroughs

Description
• 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
Diagram
flowchart 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

Loading

Grey Divider

File Changes

1. lockfile/utils/src/pkgSnapshotToResolution.ts 🐞 Bug fix +39/-3

Add integrity validation for tarball resolutions

• Add integrity validation for tarball-shaped resolutions at lockfile-read time
• Throw ERR_PNPM_MISSING_TARBALL_INTEGRITY when remote tarballs lack integrity
• Exempt git-hosted tarballs (via gitHosted flag or URL pattern matching) and file: tarballs
• Add isGitHostedTarballUrl helper to detect legacy git-hosted tarball URLs

lockfile/utils/src/pkgSnapshotToResolution.ts


2. lockfile/utils/test/pkgSnapshotToResolution.ts 🧪 Tests +58/-0

Add comprehensive integrity validation tests

• Add integrity field to existing CDN tarball test case
• Add test suite verifying rejection of remote tarballs without integrity
• Add test suite verifying exemption for git-hosted and file: tarballs
• Cover both explicit gitHosted flag and URL pattern fallback scenarios

lockfile/utils/test/pkgSnapshotToResolution.ts


3. .changeset/require-tarball-integrity.md 📝 Documentation +6/-0

Add changeset for tarball integrity fix

• Document security fix for missing tarball integrity validation
• Explain attack vector and mitigation strategy
• Note exemptions for git-hosted and file: tarballs

.changeset/require-tarball-integrity.md


View more (3)
4. lockfile/utils/package.json Dependencies +1/-0

Add error package dependency

• Add @pnpm/error as direct dependency for error handling

lockfile/utils/package.json


5. lockfile/utils/tsconfig.json ⚙️ Configuration changes +3/-0

Add error package TypeScript reference

• Add TypeScript project reference to @pnpm/error package

lockfile/utils/tsconfig.json


6. pnpm-lock.yaml Dependencies +3/-0

Update lockfile with new dependency

• Update lockfile to reflect new @pnpm/error dependency in lockfile/utils

pnpm-lock.yaml


Grey Divider

Qodo Logo

@zkochan zkochan merged commit b8196b8 into release/10 May 27, 2026
14 checks passed
@zkochan zkochan deleted the backport-11966-v10 branch May 27, 2026 22:44
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