fix(parser): flatten nested CycloneDX components so they are diffed#29
Open
dmchaledev wants to merge 1 commit into
Open
fix(parser): flatten nested CycloneDX components so they are diffed#29dmchaledev wants to merge 1 commit into
dmchaledev wants to merge 1 commit into
Conversation
CycloneDX components form a tree: a component may carry its own nested `components` array (sub-assemblies / bundled dependencies), a valid and documented structure emitted by several generators. parseCycloneDX only read the top-level array, so every nested component was silently dropped and never appeared as added/removed/upgraded — a false-negative for a supply-chain tool. Recursively flatten the component tree depth-first (parent before children, preserving document order). The change is confined to the parser; the canonical SBOM model is unchanged, so diff/reporter/CLI are untouched. Adds a test covering two levels of nesting. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015zPMEojF5G1qFdQUrxfaXC
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
CycloneDX components form a tree: a component may carry its own nested
componentsarray (sub-assemblies / bundled dependencies). This is a valid, documented part of the CycloneDX spec and is emitted by several generators.parseCycloneDXonly read the top-levelobj.componentsarray (src/parser.ts:22), so every nested component was silently dropped beforediff()ever saw it.For a package keyworded
supply-chain-security/vulnerability-management, that's a silent false-negative: a nested dependency that was added, removed, upgraded, or replaced never shows up in the report at all.Reproduction (before this change)
Change
flattenCycloneDXComponents()helper that walks the component tree depth-first (parent before children), preserving document order, and collects every component — top-level and nested.parseCycloneDX()in place of the single top-level read.JSON input cannot contain reference cycles, so the recursion always terminates. Non-object / non-array entries are skipped defensively.
Scope & compatibility
parser.ts. The canonicalSBOMmodel is unchanged, sodiff.ts,reporter.ts, andcli.tsare untouched — this composes cleanly with every open PR (they all operate on the post-parse model).components) parse exactly as before.Tests
Adds a
parser.test.tscase covering two levels of nesting, asserting depth-first order (['app', 'lodash', 'express', 'qs']) and that a deeply-nested component's fields are preserved. Full suite: 30 passing;typecheck,lint, andbuildall clean.🤖 Generated with Claude Code
https://claude.ai/code/session_015zPMEojF5G1qFdQUrxfaXC
Generated by Claude Code