Skip to content

feat(scanner): expose Trivy dependency graph fields on Library#2552

Merged
shino merged 5 commits into
masterfrom
package_relationship
May 18, 2026
Merged

feat(scanner): expose Trivy dependency graph fields on Library#2552
shino merged 5 commits into
masterfrom
package_relationship

Conversation

@sadayuki-matsuno
Copy link
Copy Markdown
Collaborator

@sadayuki-matsuno sadayuki-matsuno commented May 17, 2026

What did you implement:

This PR threads three Trivy Package fields — ID, Relationship, and DependsOn — through scanner.convertLibWithScanner() so they survive on the models.Library struct. Trivy already populates these fields in its language-package analyzers, but vuls currently drops them during the ftypes.Packagemodels.Library conversion.

Surfacing this information lets any consumer of LibraryScanner results:

  1. Tell whether a library is a direct or indirect dependency, instead of presenting one flat list — Trivy already knows, vuls just wasn't passing the answer along.
  2. Reconstruct the dependency graph emitted by Trivy and resolve the direct-dependency origin of an indirect library. This answers "which library do I need to update to remove this transitive vulnerable dep?". The reconstruction uses ID as the key and DependsOn as edges, which is the same model Trivy exposes via Packages.ParentDeps().

The change is intentionally minimal and additive: existing fields are untouched and no new dependencies are introduced. JSON output gains three new keys — ID, Relationship, DependsOn — each tagged omitempty. ID and DependsOn are dropped when Trivy does not populate them, so libraries from analyzers that don't emit package IDs look unchanged. Relationship, however, is always emitted: Trivy's Relationship.String() returns the literal "unknown" for the zero value (RelationshipUnknown), and we keep that string deliberately so the JSON tells consumers "Trivy did not classify this dependency" instead of silently dropping the field. Consumers that diff vuls.json across versions will therefore see a new "Relationship": "..." key on every library entry.

What changed

  • models/library.go: add ID, Relationship, DependsOn to Library (all omitempty). Relationship is stored as the stringified form ("direct" | "indirect" | "workspace" | "root" | "unknown") so the models package does not gain a dependency on aquasecurity/trivy/pkg/fanal/types.
  • scanner/library.go: copy lib.ID, lib.Relationship.String(), and lib.DependsOn in convertLibWithScanner(). Three additional lines.
  • scanner/library_test.go: update existing wants with Relationship: "unknown" (the zero-value string Trivy returns for RelationshipUnknown) and add a new table-driven case covering direct / indirect / unknown packages with DependsOn edges.

Fixes # (no associated issue — happy to file one first if preferred)

Type of change

  • New feature (non-breaking change which adds functionality)

How Has This Been Tested?

  • go test ./scanner/... -run Test_convertLibWithScanner -v
    • 4/4 PASS (3 existing + 1 newly added case covering ID/Relationship/DependsOn).
  • go test ./models/... -count=1
    • PASS.
  • make test was not run end-to-end locally because scanner.TestAnalyzeLibrary_Golden / TestAnalyzeLibrary_PomOnline require the integration/ submodule data, which is unavailable in my checkout. These failures are unrelated to this change (their own log says "run: git submodule update --init, or check the CI integration checkout step") and should pass on CI where the submodule is checked out.

Reproduction commands:

go test ./scanner/ -run Test_convertLibWithScanner -v
go test ./models/...

Backward compatibility

  • All existing fields on models.Library are unchanged.
  • New fields use json:",omitempty". Old vuls.json payloads remain valid for unmarshalling.
    • ID and DependsOn are absent from the output when Trivy does not populate them, so most libraries scanned by analyzers that don't produce a dependency graph (e.g., bare gemspec, NodePkg) remain visually unchanged.
    • Relationship is the one new key that appears on every library. For packages whose upstream Trivy Relationship is RelationshipUnknown (the zero value — i.e., the language analyzer did not classify the dependency), the field is serialized as "unknown" rather than omitted. This is intentional: an explicit "unknown" distinguishes "Trivy looked and could not tell" from "this field does not exist in this vuls version," which matters for consumers comparing scans across vuls releases. Downstream tooling that hashes or diffs vuls.json will need to either accept the new key or filter it.
  • No new imports are added (ftypes was already imported by both files).
  • lib.Relationship.String() is the same conversion Trivy uses internally; for the zero value (RelationshipUnknown) it returns the literal string "unknown", which is reflected in the updated existing-test expectations.

Checklist:

You don't have to satisfy all of the following.

  • Write tests
  • Write documentation
  • Check that there aren't other open pull requests for the same issue/feature
  • Format your source code by make fmt
  • Pass the test by make test
  • Provide verification config / commands
  • Enable "Allow edits from maintainers" for this PR
  • Update the messages below

Is this ready for review?: YES

Reference

@sadayuki-matsuno sadayuki-matsuno changed the title jfeat(scanner): expose Trivy dependency graph fields on Library feat(scanner): expose Trivy dependency graph fields on Library May 17, 2026
@MaineK00n MaineK00n requested a review from shino May 17, 2026 12:54
@shino
Copy link
Copy Markdown
Collaborator

shino commented May 18, 2026

Description updated

Comment thread scanner/analyze_golden_test.go
Comment thread scanner/analyze_golden_test.go
Copy link
Copy Markdown
Collaborator

@shino shino left a comment

Choose a reason for hiding this comment

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

Thanks a lot!! 🎊

@shino shino merged commit 140017b into master May 18, 2026
7 checks passed
@shino shino deleted the package_relationship branch May 18, 2026 09:39
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