Skip to content

Conversation

@DmitriyLewen
Copy link
Contributor

Description

This PR fixes an issue with matching vulnerabilities to packages and components when working with SBOM (Software Bill of Materials) files. The main problem was that vulnerabilities weren't being properly matched to their corresponding
components during SBOM processing, particularly in VEX (Vulnerability Exploitability eXchange) filtering scenarios.

The solution introduces a new BOMID field that provides a reliable UUID-based identifier for matching components between decoded SBOM data and vulnerability information. This ensures accurate component-to-vulnerability associations in
both SBOM scanning mode and regular scanning modes.

Made Changes

  • Added BOMID field: Introduced BOMID uuid.UUID field to PkgIdentifier struct in pkg/fanal/types/package.go to uniquely identify SBOM components
  • Enhanced component matching: Updated Match() method to check BOMID first when matching package identifiers
  • SBOM decoding integration: Modified pkg/sbom/io/decode.go to populate the BOMID field with the component's UUID during SBOM decoding
  • Improved vulnerability mapping: Refactored pkg/sbom/io/encode.go to use BOMID instead of BOM-Ref for vulnerability-to-component mapping, providing more reliable associations
  • Fixed VEX filtering: Updated pkg/vex/vex.go to use a hybrid approach for component matching:
    • Uses BOMID for SBOM mode scenarios
    • Falls back to UID for regular scanning modes
    • Added comprehensive documentation explaining the key selection logic

These changes ensure that vulnerabilities are correctly filtered and associated with their corresponding components regardless of whether they come from SBOM files or regular package scans.

Related issues

Related PRs

Checklist

  • I've read the guidelines for contributing to this repository.
  • I've followed the conventions in the PR title.
  • I've added tests that prove my fix is effective or that my feature works.
  • I've updated the documentation with the relevant information (if needed).
  • I've added usage information (if the PR introduces new options)
  • I've included a "before" and "after" example to the description (if the PR is a user interface change).

- fill BOMID only when decode SBOM
- use BOMID to match component and vuln

components := lo.MapEntries(bom.Components(), func(_ uuid.UUID, component *core.Component) (string, *core.Component) {
return component.PkgIdentifier.UID, component
return cmp.Or(component.ID().String(), component.PkgIdentifier.UID), component
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The main problem in #9593 is that the decoded BOM component (from a reused BOM) doesn’t have a UID field.

I tried to fix this in this package, but we run into the following scenarios:

mode component fields vulnerability fields
fs mode UID + PURL UID + PURL
scan CycloneDX file UID + bom-ref + PURL UID + bom-ref + PURL
scan SPDX file PURL UID + PURL

There are two problems:

  • We can’t define a consistent matching order, so in some cases we have to check the components map up to three times.
  • We have to rely on PURL for SPDX, which isn’t ideal because multiple packages can share the same PURL.

I thought about adding a new field for SPDX-ID, but in that case there would still be a question of how to efficiently check the components map.


So I chose this approach instead.
BOMID is used only for decoded components, which allows us to reliably match components with vulnerabilities/packages.

@knqyf263 let me know what you think. If this looks good, I’ll go ahead and update the tests, comments, logs, etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I found another approach:
we can calculate the UID after decoding the package and then update the component with this UID.
Please take a look at this branch: https://github.com/DmitriyLewen/trivy/tree/fix/add-uid-for-decoded-bom-components

Also, we can use the UID to match components with vulnerabilities.

Copy link
Collaborator

Choose a reason for hiding this comment

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

we can calculate the UID after decoding the package and then update the component with this UID.

After reading the content of the issue (and before reading this PR), I was just about to propose exactly this change. I think it’s generally good, but wouldn’t it be better to insert the UID inside decodePackage?

pkg.Identifier.UID = dependency.UID(pkg.FilePath, *pkg)
return pkg, nil

https://github.com/DmitriyLewen/trivy/blob/3cf4b7936646db692947085540e9cd65948fa7a4/pkg/sbom/io/decode.go#L251

// Overwrite component with UID for package
c.PkgIdentifier.UID = pkg.Identifier.UID
m.bom.AddComponent(c)

Since the returned package will be stored in m.pkgs, it might be better to save the UID before that point.

Copy link
Collaborator

Choose a reason for hiding this comment

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

However, I planned to add BOMID or something similar in the future. It may be a good idea to do that now.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I'll make a quick PoC—just a second.

Copy link
Contributor Author

@DmitriyLewen DmitriyLewen Oct 7, 2025

Choose a reason for hiding this comment

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

I was thinking about that too.
IIUC, we'll need to revert some changes:

  1. aff03eb#diff-bda89d30f6e4b3fac0df2f83407739dc83f36828c830d5860fa5b9cf61083260
  2. aff03eb#diff-bda89d30f6e4b3fac0df2f83407739dc83f36828c830d5860fa5b9cf61083260L288-L291 (i am not sure about this)

This means we’ll need to update the logic for the root component in two places (for the reusable BOM and for the VEX case).
It shouldn’t be difficult, but it’s something we need to keep in mind.

Copy link
Collaborator

Choose a reason for hiding this comment

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

File selection in GitHub commit URLs doesn’t navigate properly (is it just my browser?), so I couldn’t see which file you were referring to. Since we only need the tree in VEX, I thought it would be fine to regenerate it, but is there any issue with that?

Copy link
Contributor Author

@DmitriyLewen DmitriyLewen Oct 7, 2025

Choose a reason for hiding this comment

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

(is it just my browser?)

same for me...

I wrote about these changes (encode.go file):
изображение
изображение

UPD:
IIUC we need to reuse the root component since there might be a case where the root component (from the scanned sbom) uses a different purl.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I tried to write a test to demonstrate my thoughts, but it looks like this is a very hard-to-reproduce case and probably doesn’t occur in normal usage.
So for now, I’ll apply your suggested changes and create another PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

created #9604

@DmitriyLewen DmitriyLewen changed the title feat(sbom): add BOMID field to match packages and decoded components feat(sbom): add BOMID field to match packages and decoded BOM components Oct 6, 2025
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.

bug(vex): VEX suppression no longer works in sbom mode starting from v0.67.0.

2 participants