sort order for matches should consider fix info (#1933)

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
This commit is contained in:
Alex Goodman 2024-06-12 11:48:23 -04:00 committed by GitHub
parent 9d28137f78
commit 97edf42c26
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 67 additions and 5 deletions

View file

@ -68,14 +68,56 @@ func TestMatchesSortMixedDimensions(t *testing.T) {
Type: syftPkg.RpmPkg,
},
}
sixth := Match{
Vulnerability: vulnerability.Vulnerability{
ID: "CVE-2020-0020",
Fix: vulnerability.Fix{
Versions: []string{"2.0.0", "1.0.0"},
},
},
Package: pkg.Package{
ID: pkg.ID(uuid.NewString()),
Name: "package-d",
Version: "2.0.0",
Type: syftPkg.RpmPkg,
},
}
seventh := Match{
Vulnerability: vulnerability.Vulnerability{
ID: "CVE-2020-0020",
Fix: vulnerability.Fix{
Versions: []string{"2.0.1"},
},
},
Package: pkg.Package{
ID: pkg.ID(uuid.NewString()),
Name: "package-d",
Version: "2.0.0",
Type: syftPkg.RpmPkg,
},
}
eighth := Match{
Vulnerability: vulnerability.Vulnerability{
ID: "CVE-2020-0020",
Fix: vulnerability.Fix{
Versions: []string{"3.0.0"},
},
},
Package: pkg.Package{
ID: pkg.ID(uuid.NewString()),
Name: "package-d",
Version: "2.0.0",
Type: syftPkg.RpmPkg,
},
}
input := []Match{
// shuffle vulnerability id, package name, package version, and package type
fifth, third, first, second, fourth,
fifth, eighth, third, seventh, first, sixth, second, fourth,
}
matches := NewMatches(input...)
assertMatchOrder(t, []Match{first, second, third, fourth, fifth}, matches.Sorted())
assertMatchOrder(t, []Match{first, second, third, fourth, fifth, sixth, seventh, eighth}, matches.Sorted())
}

View file

@ -1,6 +1,9 @@
package match
import "sort"
import (
"sort"
"strings"
)
var _ sort.Interface = (*ByElements)(nil)
@ -16,6 +19,17 @@ func (m ByElements) Less(i, j int) bool {
if m[i].Vulnerability.ID == m[j].Vulnerability.ID {
if m[i].Package.Name == m[j].Package.Name {
if m[i].Package.Version == m[j].Package.Version {
if m[i].Package.Type == m[j].Package.Type {
// this is an approximate ordering, but is not accurate in terms of semver and other version formats
// but stability is what is important here, not the accuracy of the sort.
fixVersions1 := m[i].Vulnerability.Fix.Versions
fixVersions2 := m[j].Vulnerability.Fix.Versions
sort.Strings(fixVersions1)
sort.Strings(fixVersions2)
fixStr1 := strings.Join(fixVersions1, ",")
fixStr2 := strings.Join(fixVersions2, ",")
return fixStr1 < fixStr2
}
return m[i].Package.Type < m[j].Package.Type
}
return m[i].Package.Version < m[j].Package.Version

View file

@ -123,6 +123,7 @@ func sortRows(rows [][]string) [][]string {
var (
name = 0
ver = 1
fix = 2
packageType = 3
vuln = 4
sev = 5
@ -134,6 +135,9 @@ func sortRows(rows [][]string) [][]string {
if rows[i][ver] == rows[j][ver] {
if rows[i][packageType] == rows[j][packageType] {
if models.SeverityScore(rows[i][sev]) == models.SeverityScore(rows[j][sev]) {
if rows[i][vuln] == rows[j][vuln] {
return rows[i][fix] < rows[j][fix]
}
// we use > here to get the most recently filed vulnerabilities
// to show at the top of the severity
return rows[i][vuln] > rows[j][vuln]

View file

@ -164,7 +164,8 @@ func TestSortRows(t *testing.T) {
{"a", "v0.1.0", "", "deb", "CVE-2018-9996", "Critical"},
{"a", "v0.2.0", "", "deb", "CVE-2010-9996", "High"},
{"b", "v0.2.0", "", "deb", "CVE-2010-9996", "Medium"},
{"b", "v0.2.0", "", "deb", "CVE-2019-9996", "High"},
{"b", "v0.2.0", "2.0.0", "deb", "CVE-2019-9996", "High"},
{"b", "v0.2.0", "1.0.0", "deb", "CVE-2019-9996", "High"},
{"d", "v0.4.0", "", "node", "CVE-2011-9996", "Low"},
{"d", "v0.4.0", "", "node", "CVE-2012-9996", "Negligible"},
{"c", "v0.6.0", "", "node", "CVE-2013-9996", "Critical"},
@ -174,7 +175,8 @@ func TestSortRows(t *testing.T) {
{"a", "v0.1.0", "", "deb", "CVE-2019-9996", "Critical"},
{"a", "v0.1.0", "", "deb", "CVE-2018-9996", "Critical"},
{"a", "v0.2.0", "", "deb", "CVE-2010-9996", "High"},
{"b", "v0.2.0", "", "deb", "CVE-2019-9996", "High"},
{"b", "v0.2.0", "1.0.0", "deb", "CVE-2019-9996", "High"},
{"b", "v0.2.0", "2.0.0", "deb", "CVE-2019-9996", "High"},
{"b", "v0.2.0", "", "deb", "CVE-2010-9996", "Medium"},
{"c", "v0.6.0", "", "node", "CVE-2013-9996", "Critical"},
{"d", "v0.4.0", "", "node", "CVE-2011-9996", "Low"},