fix(apk): find secdb entries for origin packages (#1602)

Signed-off-by: Dan Luhring <dluhring@chainguard.dev>
This commit is contained in:
Dan Luhring 2024-09-16 09:15:22 -04:00 committed by GitHub
parent 78945be951
commit c40aab240f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 73 additions and 9 deletions

View file

@ -28,15 +28,15 @@ func (m *Matcher) Type() match.MatcherType {
func (m *Matcher) Match(store vulnerability.Provider, d *distro.Distro, p pkg.Package) ([]match.Match, error) {
var matches = make([]match.Match, 0)
// direct matches with package
directMatches, err := m.findApkPackage(store, d, p)
// direct matches with package itself
directMatches, err := m.findMatchesForPackage(store, d, p)
if err != nil {
return nil, err
}
matches = append(matches, directMatches...)
// indirect matches with package source
indirectMatches, err := m.matchBySourceIndirection(store, d, p)
// indirect matches, via package's origin package
indirectMatches, err := m.findMatchesForOriginPackage(store, d, p)
if err != nil {
return nil, err
}
@ -61,6 +61,14 @@ func (m *Matcher) cpeMatchesWithoutSecDBFixes(store vulnerability.Provider, d *d
return nil, err
}
for _, upstreamPkg := range pkg.UpstreamPackages(p) {
secDBVulnerabilitiesForUpstream, err := store.GetByDistro(d, upstreamPkg)
if err != nil {
return nil, err
}
secDBVulnerabilities = append(secDBVulnerabilities, secDBVulnerabilitiesForUpstream...)
}
secDBVulnerabilitiesByID := vulnerabilitiesByID(secDBVulnerabilities)
verObj, err := version.NewVersionFromPkg(p)
@ -139,8 +147,8 @@ func vulnerabilitiesByID(vulns []vulnerability.Vulnerability) map[string][]vulne
return results
}
func (m *Matcher) findApkPackage(store vulnerability.Provider, d *distro.Distro, p pkg.Package) ([]match.Match, error) {
// find Alpine SecDB matches for the given package name and version
func (m *Matcher) findMatchesForPackage(store vulnerability.Provider, d *distro.Distro, p pkg.Package) ([]match.Match, error) {
// find SecDB matches for the given package name and version
secDBMatches, err := search.ByPackageDistro(store, d, p, m.Type())
if err != nil {
return nil, err
@ -163,11 +171,11 @@ func (m *Matcher) findApkPackage(store vulnerability.Provider, d *distro.Distro,
return matches, nil
}
func (m *Matcher) matchBySourceIndirection(store vulnerability.Provider, d *distro.Distro, p pkg.Package) ([]match.Match, error) {
func (m *Matcher) findMatchesForOriginPackage(store vulnerability.Provider, d *distro.Distro, p pkg.Package) ([]match.Match, error) {
var matches []match.Match
for _, indirectPackage := range pkg.UpstreamPackages(p) {
indirectMatches, err := m.findApkPackage(store, d, indirectPackage)
indirectMatches, err := m.findMatchesForPackage(store, d, indirectPackage)
if err != nil {
return nil, fmt.Errorf("failed to find vulnerabilities for apk upstream source package: %w", err)
}

View file

@ -25,7 +25,7 @@ type mockStore struct {
}
func (s *mockStore) GetVulnerability(namespace, id string) ([]grypeDB.Vulnerability, error) {
//TODO implement me
// TODO implement me
panic("implement me")
}
@ -556,6 +556,62 @@ func TestNvdMatchesNoConstraintWithSecDBFix(t *testing.T) {
assertMatches(t, expected, actual)
}
func TestNVDMatchCanceledByOriginPackageInSecDB(t *testing.T) {
nvdVuln := grypeDB.Vulnerability{
ID: "CVE-2015-3211",
VersionFormat: "unknown",
CPEs: []string{"cpe:2.3:a:php-fpm:php-fpm:-:*:*:*:*:*:*:*"},
Namespace: "nvd:cpe",
}
secDBVuln := grypeDB.Vulnerability{
ID: "CVE-2015-3211",
VersionConstraint: "< 0",
VersionFormat: "apk",
Namespace: "wolfi:distro:wolfi:rolling",
}
store := mockStore{
backend: map[string]map[string][]grypeDB.Vulnerability{
"nvd:cpe": {
"php-fpm": []grypeDB.Vulnerability{nvdVuln},
},
"wolfi:distro:wolfi:rolling": {
"php-8.3": []grypeDB.Vulnerability{secDBVuln},
},
},
}
provider, err := db.NewVulnerabilityProvider(&store)
require.NoError(t, err)
m := Matcher{}
d, err := distro.New(distro.Wolfi, "")
if err != nil {
t.Fatalf("failed to create a new distro: %+v", err)
}
p := pkg.Package{
ID: pkg.ID(uuid.NewString()),
Name: "php-8.3-fpm",
Version: "8.3.11-r0",
Type: syftPkg.ApkPkg,
CPEs: []cpe.CPE{
cpe.Must("cpe:2.3:a:php-fpm:php-fpm:8.3.11-r0:*:*:*:*:*:*:*", ""),
},
Upstreams: []pkg.UpstreamPackage{
{
Name: "php-8.3",
Version: "8.3.11-r0",
},
},
}
expected := []match.Match{}
actual, err := m.Match(provider, d, p)
assert.NoError(t, err)
assertMatches(t, expected, actual)
}
func TestDistroMatchBySourceIndirection(t *testing.T) {
secDbVuln := grypeDB.Vulnerability{