Implemented VERS approach for PURL version matching with VERSATILE.
Description
Implemented the VERS approach for comparing versioning schemes more reliably using the versatile/versatile-core/src/main/java/io/github/nscuro/versatile at main · nscuro/versatile package. Key implementations:
- VulnerableSoftware.java now contains a vers field, building a comparable VERS for given constraints.
- InternalAnalysisTask.java and AbstractVulnerableSoftwareAnalysisTask.java now differ between CPE and PURL matching of versions. In case a purl is given, the tasks now perform contains() based on Versions and VersionRanges based on versatile. The logic of CPE matching stayed the same.
- Included Tests, in line with existing Cpe Matching Tests.
- VersionPolicyEvaluator.java now includes condition matching based on PURL and on CPEs.
Open for discussions!
Addressed Issue
Addressed issue #2826.
Additional Details
Used ChatGPT and Copilot to understand existing codebase.
Checklist
- [x] I have read and understand the contributing guidelines
- [ ] This PR fixes a defect, and I have provided tests to verify that the fix is effective
- [x] This PR implements an enhancement, and I have provided tests to verify that it works as intended
- [ ] This PR introduces changes to the database model, and I have added corresponding update logic
- [ ] This PR introduces new or alters existing behavior, and I have updated the documentation accordingly
:white_check_mark: Snyk checks have passed. No issues have been found so far.
| Status | Scanner | Total (0) | ||||
|---|---|---|---|---|---|---|
| :white_check_mark: | Open Source Security | 0 | 0 | 0 | 0 | 0 issues |
:computer: Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.
Coverage summary from Codacy
See diff coverage on Codacy
| Coverage variation | Diff coverage |
|---|---|
| :white_check_mark: +0.03% (target: -1.00%) | :white_check_mark: 85.71% (target: 70.00%) |
Coverage variation details
| Coverable lines | Covered lines | Coverage | |
|---|---|---|---|
| Common ancestor commit (e822f43c1cdde22acb7660a8f70a4a280bdc3b7d) | 24092 | 19492 | 80.91% |
| Head commit (675f9389e14353c1b31561dcecc837b8db235b66) | 24218 (+126) | 19601 (+109) | 80.94% (+0.03%) |
Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch: <coverage of head commit> - <coverage of common ancestor commit>
Diff coverage details
| Coverable lines | Covered lines | Diff coverage | |
|---|---|---|---|
| Pull request (#5591) | 140 | 120 | 85.71% |
Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified: <covered lines added or modified>/<coverable lines added or modified> * 100%
See your quality gate settings Change summary preferences
Have you done any testing WRT the internal analysis using data from GitHub Advisories or OSV? It would be good to get an idea how this performs with real-world data.
Yes, I simply added the components that Github Advisories had assigned vulnerabilities to to a test project on a random basis. Vulnerabilities were correctly identified. I did it for most of the already supported schemes of versatile and one or two non-supported ones (which should have resulted in generic then). Would you like further info about that?
Doing some testing as well now. I noticed there is a concurrency issue in versatile which I'll need to fix:
2025-12-04 16:28:30,781 ERROR [VulnerabilityAnalysisTask] Failed to analyze project [eventToken=2b9777f2-6c5c-43a4-8a32-5ffa61980fa7, projectName=apache/flink:1.18, vulnAnalysisLevel=BOM_UPLOAD_ANALYSIS, projectUuid=d35d2293-dd18-44e1-8828-861719424d8e, projectVersion=f6553722-66d2-4467-aa98-0964f8ee5493]
java.util.ConcurrentModificationException: null
at java.base/java.util.HashMap.computeIfAbsent(HashMap.java:1230)
at io.github.nscuro.versatile.VersionFactory.forScheme(VersionFactory.java:41)
at org.dependencytrack.tasks.scanners.AbstractVulnerableSoftwareAnalysisTask.analyzePurlVersionRange(AbstractVulnerableSoftwareAnalysisTask.java:87)
at org.dependencytrack.tasks.scanners.AbstractVulnerableSoftwareAnalysisTask.analyzeVersionRange(AbstractVulnerableSoftwareAnalysisTask.java:71)
at org.dependencytrack.tasks.scanners.InternalAnalysisTask.versionRangeAnalysis(InternalAnalysisTask.java:156)
at org.dependencytrack.tasks.scanners.InternalAnalysisTask.analyze(InternalAnalysisTask.java:91)
at org.dependencytrack.tasks.scanners.InternalAnalysisTask.inform(InternalAnalysisTask.java:65)
at org.dependencytrack.tasks.VulnerabilityAnalysisTask.analyzeComponents(VulnerabilityAnalysisTask.java:288)
Released versatile 0.14.0 which fixes the above and also adds support for Alpine and Python versions: https://github.com/nscuro/versatile/releases/tag/v0.14.0
This should then also resolve https://github.com/DependencyTrack/dependency-track/issues/3808
Released versatile 0.14.0 which fixes the above and also adds support for Alpine and Python versions: https://github.com/nscuro/versatile/releases/tag/v0.14.0
This should then also resolve #3808
Thank you for adding this! I already deleted my PR fixing #3808 with the minimal change.