fix(diff): detect upgrades for versioned purls (headline feature was broken for real SBOMs) - #57
Open
dmchaledev wants to merge 1 commit into
Open
fix(diff): detect upgrades for versioned purls (headline feature was broken for real SBOMs)#57dmchaledev wants to merge 1 commit into
dmchaledev wants to merge 1 commit into
Conversation
Component identity was keyed on the full purl, which embeds the version (e.g. pkg:npm/lodash@4.17.21). Real SBOM generators (syft, cdxgen, Trivy) always emit versioned purls, so a simple version bump was reported as a removal + addition and the `upgraded` list stayed empty — defeating the headline "version upgrades" feature for essentially every real input. Derive component identity from the version-independent purl coordinates (stripping @Version plus any ?qualifiers/#subpath), falling back to name when no purl exists. Scoped npm purls stay correct because the spec percent-encodes any literal @ in the name. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DZRdkf7mAryZDiNcsAG1n4
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
Upgrade detection — a headline feature of this tool ("Highlights added, removed, upgraded dependencies") — is broken for essentially every real-world SBOM. A simple patch bump is reported as a removal plus an addition, and the
upgradedlist stays empty.Root cause
buildComponentMapinsrc/diff.tskeyed each component by its full purl:But a purl embeds the version (
pkg:npm/lodash@4.17.21). Real SBOM generators (syft, cdxgen, Trivy, …) always emit versioned purls, solodash@4.17.20andlodash@4.17.21get different keys — the old one looks removed, the new one looks added, and no upgrade is ever detected. Upgrades were only found in the rare case where components had no purl and matched by name (see the existing name-fallback test).Reproduction (before)
Fix
Derive component identity from the version-independent purl coordinates — strip the
@versionsuffix (plus any?qualifiers/#subpath), falling back to the component name when no purl is present. Per the purl spec any literal@in a name is percent-encoded, so scoped npm packages likepkg:npm/%40angular/core@16.0.0stay correct.After the fix the same input reports
Upgraded: 1with4.17.20 → 4.17.21, and add/remove/major-bump detection is unchanged.Changes
src/diff.ts— newcomponentKey/purlWithoutVersionhelpers;buildComponentMapkeys on version-independent identity.src/__tests__/diff.test.ts— replaced the test that documented the old broken behavior with tests asserting upgrade detection for versioned purls, purls with qualifiers, and scoped npm purls (major bump).CHANGELOG.md—Fixedentry under[Unreleased].Testing
npm test— 40 passing (was 38)npm run lint— cleannpm run build— cleanNotes / scope
Kept intentionally focused. When a single SBOM legitimately lists two versions of the same package, version-independent keys make them collapse (last-write-wins) — that is the separate concern already tracked in #50 and is out of scope here.
Generated by Claude Code