mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-13 00:00:19 -08:00
feat(redhat): support modular packages (#790)
This commit is contained in:
@@ -62,12 +62,14 @@ func (s *Scanner) Detect(osVer string, pkgs []ftypes.Package) ([]types.DetectedV
|
||||
|
||||
var vulns []types.DetectedVulnerability
|
||||
for _, pkg := range pkgs {
|
||||
if !s.isSupported(pkg) {
|
||||
if !s.isFromSupportedVendor(pkg) {
|
||||
log.Logger.Debugf("Skipping %s: unsupported vendor", pkg.Name)
|
||||
continue
|
||||
}
|
||||
|
||||
// For Red Hat Security Data API containing only source package names
|
||||
advisories, err := s.vs.Get(osVer, pkg.SrcName)
|
||||
pkgName := addModularNamespace(pkg.SrcName, pkg.Modularitylabel)
|
||||
advisories, err := s.vs.Get(osVer, pkgName)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to get Red Hat advisories: %w", err)
|
||||
}
|
||||
@@ -88,8 +90,9 @@ func (s *Scanner) Detect(osVer string, pkgs []ftypes.Package) ([]types.DetectedV
|
||||
vulns = append(vulns, vuln)
|
||||
}
|
||||
|
||||
// For Red Hat OVAL containing only binary package names
|
||||
advisories, err = s.vs.Get(osVer, pkg.Name)
|
||||
// For Red Hat OVAL v2 containing only binary package names
|
||||
pkgName = addModularNamespace(pkg.Name, pkg.Modularitylabel)
|
||||
advisories, err = s.vs.Get(osVer, pkgName)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("failed to get Red Hat advisories: %w", err)
|
||||
}
|
||||
@@ -136,20 +139,6 @@ func (s *Scanner) isSupportedVersion(now time.Time, osFamily, osVer string) bool
|
||||
return now.Before(eolDate)
|
||||
}
|
||||
|
||||
func (s *Scanner) isSupported(pkg ftypes.Package) bool {
|
||||
if !s.isFromSupportedVendor(pkg) {
|
||||
log.Logger.Debugf("Skipping %s: unsupported vendor", pkg.Name)
|
||||
return false
|
||||
}
|
||||
|
||||
// Skip modular packages until OVALv2 is supported
|
||||
if pkg.Modularitylabel != "" {
|
||||
log.Logger.Debugf("Skipping modular package %s (%s) as temporary workaround", pkg.Name, pkg.Modularitylabel)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *Scanner) isFromSupportedVendor(pkg ftypes.Package) bool {
|
||||
for _, s := range excludedVendorsSuffix {
|
||||
if strings.HasSuffix(pkg.Release, s) {
|
||||
@@ -158,3 +147,17 @@ func (s *Scanner) isFromSupportedVendor(pkg ftypes.Package) bool {
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func addModularNamespace(name, label string) string {
|
||||
// e.g. npm, nodejs:12:8030020201124152102:229f0a1c => nodejs:12::npm
|
||||
var count int
|
||||
for i, r := range label {
|
||||
if r == ':' {
|
||||
count++
|
||||
}
|
||||
if count == 2 {
|
||||
return label[:i] + "::" + name
|
||||
}
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
@@ -177,6 +177,56 @@ func TestScanner_Detect(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "happy path: modular packages",
|
||||
args: args{
|
||||
osVer: "8.3",
|
||||
pkgs: []ftypes.Package{
|
||||
{
|
||||
Name: "php",
|
||||
Version: "7.2.24",
|
||||
Release: "1.module_el8.2.0+313+b04d0a66",
|
||||
Arch: "x86_64",
|
||||
Epoch: 0,
|
||||
SrcName: "php",
|
||||
SrcVersion: "7.2.24",
|
||||
SrcRelease: "1.module_el8.2.0+313+b04d0a66",
|
||||
SrcEpoch: 0,
|
||||
Modularitylabel: "php:7.2:8020020200507003613:2c7ca891",
|
||||
Layer: ftypes.Layer{
|
||||
DiffID: "sha256:3e968ecc016e1b9aa19023798229bf2d25c813d1bf092533f38b056aff820524",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
get: []dbTypes.GetExpectation{
|
||||
{
|
||||
Args: dbTypes.GetArgs{
|
||||
Release: "8",
|
||||
PkgName: "php:7.2::php",
|
||||
},
|
||||
Returns: dbTypes.GetReturns{
|
||||
Advisories: []dbTypes.Advisory{
|
||||
{
|
||||
VulnerabilityID: "CVE-2019-11043",
|
||||
FixedVersion: "7.3.5-5.module+el8.1.0+4560+e0eee7d6",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: []types.DetectedVulnerability{
|
||||
{
|
||||
VulnerabilityID: "CVE-2019-11043",
|
||||
PkgName: "php",
|
||||
InstalledVersion: "7.2.24-1.module_el8.2.0+313+b04d0a66",
|
||||
FixedVersion: "7.3.5-5.module+el8.1.0+4560+e0eee7d6",
|
||||
Layer: ftypes.Layer{
|
||||
DiffID: "sha256:3e968ecc016e1b9aa19023798229bf2d25c813d1bf092533f38b056aff820524",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "happy path: packages from remi repository are skipped",
|
||||
args: args{
|
||||
@@ -216,46 +266,6 @@ func TestScanner_Detect(t *testing.T) {
|
||||
},
|
||||
want: []types.DetectedVulnerability(nil),
|
||||
},
|
||||
{
|
||||
name: "happy path: modular packages are skipped",
|
||||
args: args{
|
||||
osVer: "8.3",
|
||||
pkgs: []ftypes.Package{
|
||||
{
|
||||
Name: "php",
|
||||
Version: "7.2.24",
|
||||
Release: "1.module_el8.2.0+313+b04d0a66",
|
||||
Arch: "x86_64",
|
||||
Epoch: 0,
|
||||
SrcName: "php",
|
||||
SrcVersion: "7.2.24",
|
||||
SrcRelease: "1.module_el8.2.0+313+b04d0a66",
|
||||
SrcEpoch: 0,
|
||||
Modularitylabel: "php:7.2:8020020200507003613:2c7ca891",
|
||||
Layer: ftypes.Layer{
|
||||
DiffID: "sha256:3e968ecc016e1b9aa19023798229bf2d25c813d1bf092533f38b056aff820524",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
get: []dbTypes.GetExpectation{
|
||||
{
|
||||
Args: dbTypes.GetArgs{
|
||||
Release: "8",
|
||||
PkgName: "php",
|
||||
},
|
||||
Returns: dbTypes.GetReturns{
|
||||
Advisories: []dbTypes.Advisory{
|
||||
{
|
||||
VulnerabilityID: "CVE-2019-11043",
|
||||
FixedVersion: "7.3.5-5.module+el8.1.0+4560+e0eee7d6",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: []types.DetectedVulnerability(nil),
|
||||
},
|
||||
{
|
||||
name: "sad path: Get returns an error",
|
||||
args: args{
|
||||
|
||||
Reference in New Issue
Block a user