Skip to content

install: pin a computed sha512 for npm packages whose manifest has no usable integrity#31327

Open
Jarred-Sumner wants to merge 3 commits into
mainfrom
claude/hardening-fix-r4-79-tarball-integrity-verification-silently-skipped-for
Open

install: pin a computed sha512 for npm packages whose manifest has no usable integrity#31327
Jarred-Sumner wants to merge 3 commits into
mainfrom
claude/hardening-fix-r4-79-tarball-integrity-verification-silently-skipped-for

Conversation

@Jarred-Sumner

Copy link
Copy Markdown
Collaborator

When a registry manifest's dist.integrity is missing, uses an unsupported algorithm, or fails to parse (and there is no shasum), npm packages were recorded in the lockfile with an empty integrity and never verified on any install. This extends the existing GitHub/remote/local tarball fallback to npm registry packages: compute a SHA-512 of the downloaded tarball and persist it into the lockfile during the resolve phase, so the first install's lockfile already carries the pin and every subsequent install verifies against it. The fallback is skipped under --no-verify.

Covers both the buffered and streaming extract paths. The resolve-phase write-back means the pin lands in the lockfile on the first install, so a second install of an unchanged project does not re-save the lockfile.

Tests added to test/cli/install/bun-install-tarball-integrity.test.ts: the pin is recorded when the manifest integrity is unparseable (unsupported algorithm and malformed base64, buffered and streaming), a swapped tarball is rejected on reinstall, and the lockfile is not re-saved on a second install when the registry provides no integrity metadata.

@robobun

robobun commented May 24, 2026

Copy link
Copy Markdown
Collaborator
Updated 8:05 PM PT - May 28th, 2026

@Jarred-Sumner, your commit f3fe5f616847638ea4cf639745e60978213c2b44 passed in Build #58769! 🎉


🧪   To try this PR locally:

bunx bun-pr 31327

That installs a local version of the PR into your bun-31327 executable, so you can run:

bun-31327 --bun

@github-actions

Copy link
Copy Markdown
Contributor

Found 1 issue this PR may fix:

  1. Consider locking tarball dependencies with a hash similar to npm dependencies #19519 - Requests locking tarball dependencies with a SHA-512 hash in bun.lock, which is exactly what this PR implements by computing and persisting a SHA-512 fallback hash when the registry's dist.integrity is missing or unusable

If this is helpful, copy the block below into the PR description to auto-close this issue on merge.

Fixes #19519

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented May 24, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@Jarred-Sumner, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 37 minutes and 51 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 3da11c95-d905-4a6b-ac13-e858caac449a

📥 Commits

Reviewing files that changed from the base of the PR and between 7459f19 and f3fe5f6.

📒 Files selected for processing (3)
  • src/install/PackageManager/processDependencyList.rs
  • src/install/TarballStream.rs
  • src/install/extract_tarball.rs

Walkthrough

Bun now computes and persists integrity checksums for npm registry tarballs that lack usable integrity metadata. The implementation integrates npm packages into the existing tarball extraction and streaming integrity pipeline, enabling sha512 fallback computation and lockfile pinning similar to GitHub and remote tarball sources.

Changes

NPM Tarball Integrity Pinning

Layer / File(s) Summary
Extract tarball integrity computation for NPM
src/install/extract_tarball.rs
ExtractTarball::run adds a ResolutionTag::Npm match arm to compute and assign integrity: propagates self.integrity when the algorithm is supported, otherwise computes Integrity::for_bytes(bytes) as SHA-512 fallback unless skip_verify is set.
Streaming integrity computation for NPM
src/install/TarballStream.rs
TarballStream::init expands compute_if_missing to cover ResolutionTag::Npm when skip_verify is false, and populate_result adds ResolutionTag::Npm to the branch that handles integrity result population alongside GitHub and other sources.
Lockfile persistence for computed NPM integrity
src/install/PackageManager/processDependencyList.rs
process_extracted_tarball_package adds integrity write-back for ResolutionTag::Npm, updating lockfile.packages[package_id].meta.integrity from computed data.integrity when the existing value is unsupported.
Test coverage for NPM registry integrity handling
test/cli/install/bun-install-tarball-integrity.test.ts
Helper utilities (buildTarball, octal) construct test tarballs. Parametrized tests verify Bun computes and pins SHA-512 when registries provide unsupported or missing integrity, then rejects swapped tarballs on reinstall. Additional test confirms lockfile is not re-saved on subsequent installs when integrity is already pinned.

Possibly related issues

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely summarizes the main change: computing and pinning SHA-512 integrity for npm packages lacking usable manifest integrity.
Description check ✅ Passed The description provides substantial detail about what the PR does and how it was verified through multiple test scenarios, going well beyond the minimal template requirements.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/cli/install/bun-install-tarball-integrity.test.ts`:
- Around line 651-660: Replace the manual for (...) loop that generates the
it(...) cases with a Jest parameterized block using describe.each([...]) so the
integrity matrix uses the repository's test convention; take the existing array
of tuples (label, dist, extraEnv) currently iterated in the for loop and pass it
into describe.each, move the it(...) body inside the describe.each callback, use
the label for the test name interpolation (e.g. `(${label})`), and preserve the
tuple names so the test still references dist and extraEnv in the same way as in
the original test function.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: fd40f88a-1c24-408d-ab2c-7f8df1cffc9b

📥 Commits

Reviewing files that changed from the base of the PR and between 49c97de and 7459f19.

📒 Files selected for processing (4)
  • src/install/PackageManager/processDependencyList.rs
  • src/install/TarballStream.rs
  • src/install/extract_tarball.rs
  • test/cli/install/bun-install-tarball-integrity.test.ts

Comment thread test/cli/install/bun-install-tarball-integrity.test.ts

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't find correctness bugs, but this changes integrity-verification and lockfile write-back behavior for npm packages in bun install (security-adjacent), so it's worth a human look — note also the build-rust CI failures on aarch64-musl and FreeBSD.

Extended reasoning...

Overview

This PR extends the existing SHA-512 fallback (already applied to GitHub / remote / local tarballs) to npm registry packages whose manifest dist.integrity is missing, uses an unsupported algorithm, or is malformed. It touches three Rust files in src/install/ (extract_tarball.rs, TarballStream.rs, PackageManager/processDependencyList.rs) plus ~210 lines of new tests. The Rust changes are small and closely mirror the existing arms for other resolution tags; the new write-back in process_extracted_tarball_package only fires when resolution.tag == Npm, package_id is valid, the extract produced a supported digest, and the lockfile entry's existing integrity is not already supported.

Security risks

This is squarely in security-sensitive territory: it governs whether and how downloaded package bytes are pinned and verified. The change is additive (it adds verification where there was previously none) and is guarded so it never overwrites an existing supported integrity, and it respects --no-verify. I don't see a way it weakens verification, but because it alters the trust/verification surface for the most common dependency source (npm registry), a human should confirm the semantics — particularly the resolve-phase write-back into lockfile.packages[...].meta.integrity and its interaction with lockfile dirty/re-save logic.

Level of scrutiny

High. bun install integrity verification and lockfile persistence are production-critical, supply-chain-relevant paths. Even though the diff is mechanically simple (adding ResolutionTag::Npm to existing match arms), the behavioral implications (every npm package without usable integrity now gets a computed pin) and the new mutation site in processDependencyList.rs warrant maintainer review.

Other factors

  • CI (robobun) reports build-rust failures on aarch64-musl and FreeBSD x64 for commit 7459f19; an autofix commit followed but the status comment still shows red.
  • Good test coverage added: parametrized over unsupported-algorithm / malformed-base64 / streaming-extractor variants, plus a no-resave-on-second-install check.
  • CodeRabbit's only comment is a stylistic nit (describe.each vs for loop) — not blocking.
  • No CODEOWNERS entry for src/install/.

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found, but this changes integrity-pinning semantics for npm registry packages (a supply-chain security path) and writes back into lockfile package metadata, so it's worth a human look.

Extended reasoning...

Overview

This PR extends the existing SHA-512 fallback (already applied to GitHub/remote/local tarballs) to npm registry packages whose manifest dist.integrity is missing, uses an unsupported algorithm, or fails to parse. It touches three Rust files in src/install/ (the buffered extractor, the streaming extractor, and the resolve-phase lockfile write-back) plus adds ~210 lines of tests. The core change is small (~30 lines) and mechanically mirrors the adjacent Github | RemoteTarball | LocalTarball arms.

Security risks

This is a supply-chain security path: it introduces TOFU pinning for npm packages that previously went permanently unverified. The change is strictly additive (it only writes a computed integrity when !meta.integrity.tag.is_supported(), never overwriting a registry-provided value) and respects --no-verify. I see no way it weakens existing verification, but because it changes when/how integrity is recorded and later enforced for the most common package source, it deserves human sign-off.

Level of scrutiny

Medium-high. The diff is small and pattern-following, but integrity verification and lockfile persistence are correctness-critical. Subtle issues (e.g., the resolve-phase write-back interacting with lockfile dirtying/re-save, or the package_id != INVALID_PACKAGE_ID guard) are the kind of thing a maintainer familiar with the install pipeline should confirm.

Other factors

Test coverage is solid: it exercises both buffered and streaming extractors, verifies swap detection on reinstall, and asserts the lockfile is not re-saved on a second install. The one CodeRabbit comment (style nit on for vs describe.each) was reasonably declined and resolved. No CODEOWNERS apply to these files.

Jarred-Sumner and others added 3 commits May 28, 2026 21:06
… usable integrity

When a registry manifest's dist.integrity is missing, uses an unsupported
algorithm, or fails to parse (and there is no shasum), npm packages were
recorded in the lockfile with an empty integrity and never verified on any
install. Extend the existing GitHub/remote/local tarball fallback to npm:
compute a SHA-512 of the downloaded tarball and persist it into the lockfile
during the resolve phase, so the first install's lockfile already carries the
pin and subsequent installs verify against it. Skipped under --no-verify.

Adds tests covering the pin being recorded for unparseable manifest integrity
(buffered and streaming extract paths), a swapped tarball being rejected on
reinstall, and the lockfile not being re-saved on a second install.
@Jarred-Sumner Jarred-Sumner force-pushed the claude/hardening-fix-r4-79-tarball-integrity-verification-silently-skipped-for branch from 77035b5 to f3fe5f6 Compare May 28, 2026 21:17
@Jarred-Sumner

Copy link
Copy Markdown
Collaborator Author

Classified build #57590: the two failing checks are buildkite/bun and buildkite/bun/debian-13-x64-asan-test-bun. The only non-flaky failure is test/js/bun/s3/s3-stream-cancel-leak.test.ts (SIGABRT from LSan-reported leaks rooted in Blob.stream() -> the S3 readable_stream path), which is unrelated to this PR — the branch only touches the install path, and neither that test nor src/runtime/webcore/s3/client.rs differ from main here. Everything else in the build is flaky retries. The base was 58 commits behind main; current main now carries #31339 and #31417 in extract_tarball.rs / TarballStream.rs (#31495 is not merged yet), and the rebase onto d632fc5 was conflict-free — main's name/size/symlink validation lands in different regions than the integrity-pinning hunks, so they compose unchanged. Rebased and force-pushed (head f3fe5f6, commits ba0dc7b / 8dfbd1e / f3fe5f6); locally bun-install-tarball-integrity, bun-install-streaming-extract, bun-install, and bun-install-registry all pass with the rebased debug build (the registry suite's auto-install symlink-cache snapshot failure reproduces identically on origin/main in this environment, so it is pre-existing and unrelated), and the new integrity-pinning cases still fail under USE_SYSTEM_BUN=1.

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't find any issues, but this changes integrity-verification and lockfile-persistence behavior for the most common package type (npm registry), so it's worth a human sign-off on the TOFU-pinning semantics.

Extended reasoning...

Overview

This PR extends the existing SHA-512 fallback (already applied to GitHub/remote/local tarballs) to npm registry packages whose manifest dist.integrity is missing, uses an unsupported algorithm, or is malformed. Three small Rust hunks:

  • extract_tarball.rs (~10 lines): adds a ResolutionTag::Npm arm mirroring the existing GitHub/remote/local arm, guarded by !self.skip_verify.
  • TarballStream.rs (~6 lines): includes Npm in compute_if_missing (when not skip_verify) and in the populate_result integrity match.
  • processDependencyList.rs (~13 lines): after extract, writes the computed integrity back into lockfile.packages[id].meta.integrity only when the existing value is unsupported.

Plus ~210 lines of new end-to-end tests covering buffered + streaming paths, swap detection on reinstall, and no-resave on a second install.

Security risks

This is security-relevant code — package integrity verification — but the change strengthens it (TOFU pinning where previously there was none). The write-back is guarded by !meta.integrity.tag.is_supported(), so a registry-provided integrity is never overwritten. --no-verify opts out, matching the existing contract. I don't see a way this weakens verification; the risk surface is a wrong hash being pinned (causing spurious failures on reinstall) or unintended lockfile churn, both of which the new tests cover.

Level of scrutiny

Medium-high. The diff is small and mechanically extends an established pattern, but it changes user-visible lockfile behavior for the dominant resolution type and lives on the integrity-verification path that every bun install exercises. A human should confirm the design decision (TOFU pinning for npm packages whose manifest integrity is unusable) and that the resolve-phase write-back into lockfile.packages composes correctly with later lockfile serialization / dirty-tracking.

Other factors

  • Bug-hunting system found nothing; the only review feedback was a CodeRabbit style nit (for-loop vs describe.each) that the author reasonably declined.
  • No CODEOWNERS coverage for src/install/.
  • Author reports the new tests pass locally on the rebased branch and fail under USE_SYSTEM_BUN=1 as expected; CI build #58769 was still running at the time of the last timeline update.

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.

2 participants