Skip to content

Commit

Permalink
fix: correct APK CPE version comparison logic
Browse files Browse the repository at this point in the history
Previously, the -r{buildindex} suffix of APK package versions were
treated as pre-release versions per the fuzzy matcher logic; however,
these should be treated as equivalent to the release version for the
purposes of collecting CPE-based matches for APK packages.

We may want to make a similar change in syft to generate cleaner CPE
versions for APK packages, but making the change in grype corrects
behaviour for previously-generated SBOMs as well.

Signed-off-by: Weston Steimel <[email protected]>
  • Loading branch information
westonsteimel committed Mar 8, 2023
1 parent 5754360 commit de25eb9
Showing 1 changed file with 33 additions and 1 deletion.
34 changes: 33 additions & 1 deletion grype/matcher/apk/matcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package apk

import (
"fmt"
"strings"

"github.com/anchore/grype/grype/distro"
"github.com/anchore/grype/grype/match"
Expand Down Expand Up @@ -45,7 +46,8 @@ func (m *Matcher) Match(store vulnerability.Provider, d *distro.Distro, p pkg.Pa

func (m *Matcher) cpeMatchesWithoutSecDBFixes(store vulnerability.Provider, d *distro.Distro, p pkg.Package) ([]match.Match, error) {
// find CPE-indexed vulnerability matches specific to the given package name and version
cpeMatches, err := search.ByPackageCPE(store, p, m.Type())
cpePackage := cpeComparablePackage(p)
cpeMatches, err := search.ByPackageCPE(store, cpePackage, m.Type())
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -101,6 +103,36 @@ cveLoop:
return finalCpeMatches, nil
}

func cpeComparablePackage(p pkg.Package) pkg.Package {
// clean the alpine package version so that it compares correctly with the CPE version comparison logic
// alpine versions are suffixed with -r{buildindex}; however, if left intact CPE comparison logic will
// incorrectly treat these as a pre-release. In actuality, we just want to treat 1.2.3-r21 as equivalent to
// 1.2.3 for purposes of CPE-based matching since the alpine fix should filter out any cases where a later
// build fixes something that was vulnerable in 1.2.3
components := strings.Split(p.Version, "-r")
cpeComparableVersion := p.Version

if len(components) == 2 {
cpeComparableVersion = components[0]
}

if cpeComparableVersion == p.Version {
return p
}

t := p
t.Version = cpeComparableVersion
t.CPEs = nil
t.CPEs = append(t.CPEs, p.CPEs...)

for index, cpe := range t.CPEs {
cpe.Version = cpeComparableVersion
t.CPEs[index] = cpe
}

return t
}

func deduplicateMatches(secDBMatches, cpeMatches []match.Match) (matches []match.Match) {
// add additional unique matches from CPE source that is unique from the SecDB matches
secDBMatchesByID := matchesByID(secDBMatches)
Expand Down

0 comments on commit de25eb9

Please sign in to comment.