install: honor bun.lockb trustedDependencies sentinel in bun pm untrusted/trust - #34327
install: honor bun.lockb trustedDependencies sentinel in bun pm untrusted/trust#34327robobun wants to merge 1 commit into
bun pm untrusted/trust#34327Conversation
…dependency The binary lockfile format stores only truncated u32 name hashes for trustedDependencies, not the names themselves. The loader inserts an empty Box<[u8]> as the documented "name unknown, hash-only match" sentinel (TrustedDependenciesSet doc comment and bun.lockb.rs loader). has_trusted_dependency rejected any entry with an empty stored name, so every trustedDependencies entry loaded from a bun.lockb failed to match. `bun pm untrusted` then listed every script-bearing package as blocked even though its postinstall had already run during install, and `bun pm trust <pkg>` re-executed the lifecycle scripts a second time. `bun install` itself was unaffected because it repopulates the map from package.json with real names before consulting it. Restore the sentinel semantics: an empty stored name is a hash-only match (the 1.3.x behavior). Entries that do carry a name still compare it to guard against truncated-hash collisions.
|
Reproduced with the CI (build 73744): the new |
|
Warning Review limit reached
Next review available in: 2 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (2)
Comment |
|
Updated 3:06 AM PT - Jul 16th, 2026
❌ @robobun, your commit fbf8912 has 3 failures in
🧪 To try this PR locally: bunx bun-pr 34327That installs a local version of the PR into your bun-34327 --bun |
There was a problem hiding this comment.
LGTM — one-line restoration of the documented bun.lockb empty-name sentinel semantics.
What was reviewed:
- Confirmed the
TrustedDependenciesSetdoc comment (lockfile.rs:109-111) and thebun.lockbloader (bun.lockb.rs:536-540) both explicitly define empty as the "hash-only match" sentinel; the fix alignshas_trusted_dependencywith that contract. - Checked all four other callers of
has_trusted_dependency(install paths) — they repopulate from package.json first so behavior is unchanged there, matching the PR's claim. - Ruled out the sibling
bun.lock.rsserializer comparison at line 521 — separate path, out of scope for this fix. - Test follows existing patterns in the file and asserts the postinstall ran exactly once.
Extended reasoning...
Overview
One-line change in src/install/lockfile.rs: has_trusted_dependency now treats an empty stored name in TrustedDependenciesSet as a match (name.is_empty() || **name == *trusted_name) instead of a non-match (!name.is_empty() && **name == *trusted_name). Adds a regression test in test/cli/install/bun-lockb.test.ts covering bun pm untrusted and bun pm trust against a binary lockfile with a trustedDependencies entry.
Security risks
trustedDependencies gates lifecycle-script execution, so widening a match here is nominally security-adjacent. However: (1) the empty sentinel is only ever inserted by the bun.lockb loader, which stores only truncated u32 hashes and physically cannot supply a name; (2) the type's own doc comment and the loader's inline comment both define empty as "hash-only match, accept"; (3) bun install already runs these scripts because it repopulates the map from package.json before consulting it — this change only fixes the reporting/re-run behavior of bun pm untrusted/trust; (4) the PR restores behavior that shipped before #31339 flipped the condition. No new attack surface is introduced.
Level of scrutiny
Low-medium. The change is a single boolean expression that brings a lookup into agreement with its type's documented contract, verified against two independent in-tree comments describing the sentinel. The test is well-targeted (asserts postinstall ran exactly once, untrusted reports 0, trust refuses with exit 1) and follows the file's established harness patterns (VerdaccioRegistry, stderrForInstall, Promise.all on pipes, exit code asserted last).
Other factors
No CODEOWNERS coverage on src/install/. No prior human review comments to address. The bug hunting system found no issues; the one candidate raised by finders (the bun.lock.rs serializer at line 521 not honoring the sentinel) was examined and is a separate serialization path outside this PR's scope.
What
In projects whose lockfile is the legacy binary
bun.lockb,bun pm untrustedlisted every package with lifecycle scripts as blocked even when it was intrustedDependenciesand its postinstall had already run during install.bun pm trust <pkg>then re-executed the postinstall a second time. The same project with a textbun.lockcorrectly reported 0 untrusted.Repro
Cause
The binary lockfile format stores only truncated u32 name hashes for
trustedDependencies, not the names. The loader (src/install/lockfile/bun.lockb.rs) inserts an emptyBox<[u8]>as the documented "name unknown, hash-only match" sentinel (see theTrustedDependenciesSetdoc comment).Lockfile::has_trusted_dependencycompared the stored name against the candidate with!name.is_empty() && **name == *trusted_name, so an empty stored name never matched. EverytrustedDependenciesentry loaded from abun.lockbtherefore failed.bun installwas unaffected because it repopulates the map frompackage.jsonwith real names before consulting it;bun pm untrusted/bun pm trustread the lockfile as loaded.Regressed in #31339, which flipped the original
name.is_empty() || **name == *aliascheck.Fix
Restore the sentinel semantics in
has_trusted_dependency: an empty stored name means "hash-only match" and accepts. Entries that do carry a name still compare it to guard against truncated-hash collisions.Verification
New test in
test/cli/install/bun-lockb.test.tscreates a project with afile:dependency that has a postinstall appending to a counter file, atrustedDependenciesentry for it, andsaveTextLockfile = false. After install it assertsbun pm untrustedreports 0 untrusted,bun pm trust deprefuses with "0 scripts ran" / "already trusted", and the postinstall ran exactly once. Fails on main at theFound 0 untrustedassertion, passes with this change.no test proof · iteration 0 · Platform-specific test(s) that do not run on this machine. Deferring to CI, which covers all platforms: test/cli/install/bun-lockb.test.ts