Skip to content

SBOM: transitive mode — inline the internal exposure chain per SBOM - #170

Open
villelaitila wants to merge 3 commits into
softagram:mainfrom
villelaitila:feature/sbom-transitive-mode
Open

SBOM: transitive mode — inline the internal exposure chain per SBOM#170
villelaitila wants to merge 3 commits into
softagram:mainfrom
villelaitila:feature/sbom-transitive-mode

Conversation

@villelaitila

Copy link
Copy Markdown
Contributor

Why

Dependency-Track (the typical consumer of these SBOMs) resolves dependency refs strictly within one uploaded BOM. The BOM-Link URNs emitted by the multi-SBOM mode are never followed across projects — DT drops them as dangling refs — so the exposure chain repoA → internal library → vulnerable 3rd-party component is invisible when each element uploads its own SBOM. DT's own recommendation for this is a merged SBOM with a full transitive dependencies graph; sgraph holds the whole cross-repo graph in one model, so it can generate exactly that, per level element.

What

generate_multi_from_sgraph(sgraph, level, transitive=True) — new opt-in mode:

  • Inlines every internal element reachable through the generalized cross-element graph as a component (softagram:internal=true), each carrying a BOM-Link back to its standalone SBOM as an externalReference of type bom
  • Pulls the 3rd-party components of the whole chain into the BOM, deduplicated; components routed in through an internal element are annotated softagram:via=<element>
  • Emits a multi-entry dependencies graph in which every ref resolves within the BOM — DT's Dependency Graph tab then shows the full path and rolls indirect vulnerabilities up to the root project
  • Cycle-safe (mutually dependent elements inline each other exactly once)
  • Default mode is unchanged (locked by test)

CLI: --transitive (requires --level).

Example output for the multi-repo test fixture:

repoa → pkg:nuget/Newtonsoft.Json@13.0.1, repob
repob → pkg:maven/org.apache.commons/commons-lang3@3.12.0   (softagram:via=repoB)

Tests

9 new tests (chain emission, provenance annotation, in-BOM ref resolution, cycle termination, default-mode regression lock, CLI flag incl. rejection without --level). Full suite: 211 passed.

Notes

A dependency whose version is governed by an imported BOM or an external
parent has no version attribute anywhere in the model, and valid_for_bom
dropped it entirely. Modern Maven centralizes versions in parents and
BOMs, so the newer the project, the emptier its SBOM: a Spring Boot
application lost its whole starter stack while a 2010-era pom came out
complete.

Three changes, one per missing shape:

- An element carrying maven coordinates and at least one incoming
  reference is now a component with a versionless purl. The incoming
  requirement keeps out the husks that version-management redirection
  leaves behind, whose references were re-pointed at versioned elements.
- extract_version falls back to parent_version, the attribute a <parent>
  block produces: the parent's exact version was already in the model
  and was discarded.
- maven_purl treats an empty version like an unresolved expression.
  Splicing it in would emit a trailing '@' - not a canonical versionless
  purl but a malformed versioned one.
Review against real stored models found four holes in the previous
commit, all in shapes the fresh-model happy path never meets:

- valid_for_bom admitted parent_version-only elements. Every model
  persisted before the analyzer wrote coordinates onto parents has that
  shape, and SBOMs are generated on demand from stored models, so the
  clause spliced space-bearing element names into generic purls for all
  existing deployments. Dropped: on coordinate-carrying models the
  coordinate branch already admits every parent.
- The coordinate branch accepted charset-rejected coordinates such as a
  ${} groupId resolved only in an external parent. Versionless, such an
  element builds no maven purl and the fallback splice emits the raw
  space-bearing name. The branch now requires is_maven_coordinate on
  both attributes.
- Two poms naming one parent at different versions collide on one
  versionless element and the attribute transfer joins the versions
  with a semicolon. maven_purl now omits such a version; the raw value
  stays disclosed in the component's version field.
- The generic fallback splice had no empty-version guard, emitting a
  trailing '@' for versionless elements that fall through maven_purl.

A cross-shape invariant test asserts no emitted purl or bom-ref in any
fixture carries a space, a semicolon, or a trailing '@'.
Dependency-Track resolves dependency refs only within one uploaded BOM;
the BOM-Link URNs of the default multi-SBOM mode are never followed
across projects, so the chain repo -> internal library -> vulnerable
3rd-party component was invisible there.

generate_multi_from_sgraph(..., transitive=True) inlines each element's
reachable internal elements as components (softagram:internal, with a
BOM-Link back to their standalone SBOM as an externalReference) plus the
3rd-party components of the whole chain (softagram:via provenance), and
emits a multi-entry dependencies graph in which every ref resolves
within the BOM. CLI: --transitive (requires --level).
@softagram-bot

Copy link
Copy Markdown

Softagram Impact Report for pull/170 (head commit: 5816d42)

TL;DR Changed code files: 3 | Directly impacted code files: 1

⭐ Change Overview

Showing the changed files, dependency changes and the impact - click for full size
(Open in Softagram Desktop for full details)

⭐ Details of Dependency Changes

details of dependency changes - click for full size
(Open in Softagram Desktop for full details)

[]

📄 Full report

Impact Report explained. Give feedback on this report to support@softagram.com

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