Skip to content

refactor(lang): use MatchVersion instead of IsVulnerable for Comparer interface #9735

Closed
DmitriyLewen wants to merge 6 commits intoaquasecurity:mainfrom
DmitriyLewen:refactor/comparer/use-match-function
Closed

refactor(lang): use MatchVersion instead of IsVulnerable for Comparer interface #9735
DmitriyLewen wants to merge 6 commits intoaquasecurity:mainfrom
DmitriyLewen:refactor/comparer/use-match-function

Conversation

@DmitriyLewen
Copy link
Contributor

Description

Refactored the Comparer interface in the library detection system to use a cleaner MatchVersion function instead of IsVulnerable. This change simplifies version comparison logic by separating constraint matching from vulnerability
assessment.

Changes

  • Interface Refactoring: Changed Comparer interface from IsVulnerable(currentVersion, advisory) to MatchVersion(currentVersion, constraint)
  • Code Organization: Moved GenericComparer from pkg/detector/library/compare/ to pkg/detector/library/compare/generic/
  • Logic Separation: Extracted common IsVulnerable function into driver.go, centralizing vulnerability assessment logic
  • Test Updates: Updated all comparator tests to use the new MatchVersion interface and added proper error handling
  • Package Cleanup: Removed unused imports and simplified package dependencies across all comparator implementations

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).

@github-actions github-actions bot added the apidiff Indicates Go API changes relevant to library consumers (CLI compatibility may be unaffected) label Oct 31, 2025
@github-actions
Copy link

📊 API Changes Detected

Semver impact: major

github.com/aquasecurity/trivy/pkg/detector/library/compare/maven
  Incompatible changes:
  - Comparer.IsVulnerable: removed
  Compatible changes:
  - Comparer.MatchVersion: added

github.com/aquasecurity/trivy/pkg/detector/library/compare/generic
  Compatible changes:
  - Comparer: added

github.com/aquasecurity/trivy/pkg/detector/library/compare/pep440
  Incompatible changes:
  - Comparer.IsVulnerable: removed
  Compatible changes:
  - Comparer.MatchVersion: added

github.com/aquasecurity/trivy/pkg/detector/library
  Compatible changes:
  - (*Driver).IsVulnerable: added

github.com/aquasecurity/trivy/pkg/detector/library/compare/bitnami
  Incompatible changes:
  - Comparer.IsVulnerable: removed
  Compatible changes:
  - Comparer.MatchVersion: added

github.com/aquasecurity/trivy/pkg/detector/library/compare/npm
  Incompatible changes:
  - Comparer.IsVulnerable: removed

github.com/aquasecurity/trivy/pkg/detector/library/compare
  Incompatible changes:
  - Comparer.IsVulnerable: removed
  - Comparer.MatchVersion: added
  - GenericComparer: removed
  - IsVulnerable: removed

github.com/aquasecurity/trivy/pkg/detector/library/compare/rubygems
  Incompatible changes:
  - Comparer.IsVulnerable: removed
  Compatible changes:
  - Comparer.MatchVersion: added

@aqua-bot aqua-bot requested a review from a team October 31, 2025 09:27

// IsVulnerable checks if the package version is vulnerable to the advisory.
func (n Comparer) IsVulnerable(ver string, advisory dbTypes.Advisory) bool {
return compare.IsVulnerable(ver, advisory, n.MatchVersion)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Here’s a more detailed description of the issue in #9427.
It’s related to an npm package.
Suppose we have a package with version 4.17.20+root.io.1 and an advisory:
• PatchedVersions: "4.17.20+root.io.5", "4.17.21"
• VulnerableVersions: "=4.17.20", ">4.17.20, <4.17.21"

When we check VulnerableVersions, the package is considered vulnerable.
But when we check PatchedVersions, 4.17.20+root.io.1 == 4.17.20+root.io.5 (because build metadata isn’t compared), so we don’t show this vulnerability.
Test for this case:
https://github.com/chait-slim/trivy/blob/790eaa7a430f9b95370d9a13695174b13c09b6d3/pkg/detector/library/rootio/rootio_test.go#L123-L154

Copy link
Collaborator

Choose a reason for hiding this comment

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

I haven’t fully followed the vulnerability detection for Root.io’s language-specific libraries yet, but it feels weird that other ecosystems would need to change just because Root.io requires special handling for version comparisons. Wouldn’t it be possible to implement the special processing only for the root ecosystem?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Let me explain in more detail:
Root.io will have multiple ecosystems, and we already have comparators for those ecosystems.

The issue is that these comparators have the IsVulnerable logic hard-coded.
This means that when comparing Root.io packages, we always check both VulnerableVersions and PatchedVersions.

However, if we want to check only VulnerableVersions (as an example), we’d have to write a new comparator/function for custom comparators.

e.g.

func (n Comparer) IsVulnerableForRootIO(ver string, advisory dbTypes.Advisory) bool {
	return root.io.IsVulnerable(ver, advisory, n.MatchVersion)
}

I think it’s more reasonable if comparators only compare versions/ranges,
and the vulnerability evaluation logic is separated: a shared (current) default implementation and a dedicated Root.io-specific one.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

When I was answering your question, I realized that this doesn’t fully solve the issue with npm packages.
So I asked a follow-up question to the Root.io team - aquasecurity/trivy-db#570 (comment)

Copy link
Collaborator

Choose a reason for hiding this comment

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

Because it doesn’t follow the ecosystem’s versioning, Root.io’s PatchedVersions can be considered inaccurate. Wouldn’t it work to perform some preprocessing? For example, we could remove only PatchedVersions before passing the data to IsVulnerable() and then add them back later.
However, I may be suggesting something off the mark since I don’t fully understand the details yet.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, you’re right. It looks like that could help.
I’ll think about it, thanks!

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 am not opposed to this proposal. Regardless of Root.io’s handling, if greater flexibility is needed, I think it’s best to make the changes as your PR suggests.

In this particular case, it just seemed that Root.io was not following the ecosystem’s versioning, so I thought it would be more natural to give them special handling before passing them to each ecosystem’s Comparer.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

When I was exploring the Root.io ecosystems, I kept “jumping” between different ecosystems and tried to think globally — that’s how the global solution appeared 😄
I wanted to add more flexibility and configuration options.

But as you correctly pointed out, Root.io didn’t consider that npm doesn’t compare build metadata, so our current approach won’t work.

Let’s leave the working logic as is for now, and if we ever need it, we can revisit this PR later.

@DmitriyLewen DmitriyLewen marked this pull request as ready for review October 31, 2025 09:59
@DmitriyLewen
Copy link
Contributor Author

I’ll close this PR for now, since it looks like there’s a simpler solution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

apidiff Indicates Go API changes relevant to library consumers (CLI compatibility may be unaffected)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants