Fix: nil memory pointer when scanResults.MetadataProvider is nil

Signed-off-by: Mehdi Moussaif <m.moussaif42@gmail.com>
This commit is contained in:
Mehdi Moussaif
2023-11-25 13:47:01 +01:00
parent 50bd74a173
commit 210b5dac33
2 changed files with 160 additions and 160 deletions

View File

@@ -44,6 +44,10 @@ func (c RegistryCredentials) IsEmpty() bool {
//
// Values equal to the threshold are considered failing, too.
func ExceedsSeverityThreshold(scanResults *models.PresenterConfig, severity vulnerability.Severity) bool {
if scanResults.MetadataProvider == nil {
return false
}
return grype.HasSeverityAtOrAbove(scanResults.MetadataProvider, severity, scanResults.Matches)
}

View File

@@ -6,7 +6,13 @@ import (
"time"
"github.com/anchore/grype/grype/db"
grypedb "github.com/anchore/grype/grype/db/v5"
"github.com/anchore/grype/grype/match"
"github.com/anchore/grype/grype/pkg"
"github.com/anchore/grype/grype/presenter/models"
"github.com/anchore/grype/grype/vulnerability"
syftPkg "github.com/anchore/syft/syft/pkg"
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
)
@@ -33,49 +39,6 @@ import (
// assert.IsType(t, Service{}, svc)
// }
// func TestRegistryCredentials(t *testing.T) {
// tt := []struct {
// name string
// username string
// password string
// want bool
// }{
// {
// name: "Valid credentials should not be empty",
// username: "user",
// password: "pass",
// want: false,
// },
// {
// name: "Empty username should be considered empty credentials",
// username: "",
// password: "pass",
// want: true,
// },
// {
// name: "Empty password should be considered empty credentials",
// username: "user",
// password: "",
// want: true,
// },
// {
// name: "Empty user and password should be considered empty credentials",
// username: "",
// password: "",
// want: true,
// },
// }
// for _, tc := range tt {
// t.Run(tc.name, func(t *testing.T) {
// creds := RegistryCredentials{Username: tc.username, Password: tc.password}
// got := creds.IsEmpty()
// assert.Equal(t, tc.want, got)
// })
// }
// }
// func TestScan(t *testing.T) {
// tt := []struct {
// name string
@@ -111,124 +74,49 @@ import (
// }
// }
// // fakeMetaProvider is a test double that fakes an actual MetadataProvider
// type fakeMetaProvider struct {
// vulnerabilities map[string]map[string][]grypedb.Vulnerability
// metadata map[string]map[string]*grypedb.VulnerabilityMetadata
// }
// fakeMetaProvider is a test double that fakes an actual MetadataProvider
type fakeMetaProvider struct {
vulnerabilities map[string]map[string][]grypedb.Vulnerability
metadata map[string]map[string]*grypedb.VulnerabilityMetadata
}
// func newFakeMetaProvider() *fakeMetaProvider {
// d := fakeMetaProvider{
// vulnerabilities: make(map[string]map[string][]grypedb.Vulnerability),
// metadata: make(map[string]map[string]*grypedb.VulnerabilityMetadata),
// }
// d.fillWithData()
// return &d
// }
// func (d *fakeMetaProvider) GetAllVulnerabilityMetadata() (*[]grypedb.VulnerabilityMetadata, error) {
// return nil, nil
// }
// func (d *fakeMetaProvider) GetVulnerabilityMatchExclusion(id string) ([]grypedb.VulnerabilityMatchExclusion, error) {
// return nil, nil
// }
// func (d *fakeMetaProvider) GetVulnerabilityMetadata(id, namespace string) (*grypedb.VulnerabilityMetadata, error) {
// return d.metadata[id][namespace], nil
// }
// func (d *fakeMetaProvider) fillWithData() {
// d.metadata["CVE-2014-fake-1"] = map[string]*grypedb.VulnerabilityMetadata{
// "debian:distro:debian:8": {
// ID: "CVE-2014-fake-1",
// Namespace: "debian:distro:debian:8",
// Severity: "medium",
// },
// }
// d.vulnerabilities["debian:distro:debian:8"] = map[string][]grypedb.Vulnerability{
// "neutron": {
// {
// PackageName: "neutron",
// Namespace: "debian:distro:debian:8",
// VersionConstraint: "< 2014.1.3-6",
// ID: "CVE-2014-fake-1",
// VersionFormat: "deb",
// },
// },
// }
// }
// func TestExceedsSeverityThreshold(t *testing.T) {
// thePkg := pkg.Package{
// ID: pkg.ID(uuid.NewString()),
// Name: "the-package",
// Version: "v0.1",
// Type: syftPkg.RpmPkg,
// }
// matches := match.NewMatches()
// matches.Add(match.Match{
// Vulnerability: vulnerability.Vulnerability{
// ID: "CVE-2014-fake-1",
// Namespace: "debian:distro:debian:8",
// },
// Package: thePkg,
// Details: match.Details{
// {
// Type: match.ExactDirectMatch,
// },
// },
// })
// tt := []struct {
// name string
// failOnSeverity string
// matches match.Matches
// expectedResult bool
// }{
// {
// name: "No severity set should pass",
// failOnSeverity: "",
// matches: matches,
// expectedResult: false,
// },
// {
// name: "Fail severity higher than vulnerability should not fail",
// failOnSeverity: "high",
// matches: matches,
// expectedResult: false,
// },
// {
// name: "Fail severity equal to vulnerability should fail",
// failOnSeverity: "medium",
// matches: matches,
// expectedResult: true,
// },
// {
// name: "Fail severity below found vuln should fail",
// failOnSeverity: "low",
// matches: matches,
// expectedResult: true,
// },
// }
// metadataProvider := db.NewVulnerabilityMetadataProvider(newFakeMetaProvider())
// for _, tc := range tt {
// t.Run(tc.name, func(t *testing.T) {
// scanResults := &models.PresenterConfig{
// Matches: tc.matches,
// MetadataProvider: metadataProvider,
// }
// inputSeverity := vulnerability.ParseSeverity(tc.failOnSeverity)
// ours := ExceedsSeverityThreshold(scanResults, inputSeverity)
// assert.Equal(t, tc.expectedResult, ours)
// })
// }
// }
func newFakeMetaProvider() *fakeMetaProvider {
d := fakeMetaProvider{
vulnerabilities: make(map[string]map[string][]grypedb.Vulnerability),
metadata: make(map[string]map[string]*grypedb.VulnerabilityMetadata),
}
d.fillWithData()
return &d
}
func (d *fakeMetaProvider) GetAllVulnerabilityMetadata() (*[]grypedb.VulnerabilityMetadata, error) {
return nil, nil
}
func (d *fakeMetaProvider) GetVulnerabilityMatchExclusion(id string) ([]grypedb.VulnerabilityMatchExclusion, error) {
return nil, nil
}
func (d *fakeMetaProvider) GetVulnerabilityMetadata(id, namespace string) (*grypedb.VulnerabilityMetadata, error) {
return d.metadata[id][namespace], nil
}
func (d *fakeMetaProvider) fillWithData() {
d.metadata["CVE-2014-fake-1"] = map[string]*grypedb.VulnerabilityMetadata{
"debian:distro:debian:8": {
ID: "CVE-2014-fake-1",
Namespace: "debian:distro:debian:8",
Severity: "medium",
},
}
d.vulnerabilities["debian:distro:debian:8"] = map[string][]grypedb.Vulnerability{
"neutron": {
{
PackageName: "neutron",
Namespace: "debian:distro:debian:8",
VersionConstraint: "< 2014.1.3-6",
ID: "CVE-2014-fake-1",
VersionFormat: "deb",
},
},
}
}
func TestParseSeverity(t *testing.T) {
tests := []struct {
@@ -306,6 +194,11 @@ func TestIsEmpty(t *testing.T) {
},
want: true,
},
{
name: "Empty struct",
creds: RegistryCredentials{},
want: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -372,6 +265,12 @@ func TestValidateDBLoad(t *testing.T) {
},
expectedErrMessage: "failed to load vulnerability db: Some error",
},
{
name: "load Error, no db status",
loadErr: errors.New("Some error"),
status: nil,
expectedErrMessage: "failed to load vulnerability db: Some error",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -431,3 +330,100 @@ func TestNewScanService(t *testing.T) {
svc := NewScanService(defaultConfig)
assert.Equal(t, defaultConfig, svc.dbCfg)
}
func TestExceedsSeverityThreshold(t *testing.T) {
my_matches := match.NewMatches()
my_matches.Add(match.Match{
Vulnerability: vulnerability.Vulnerability{
ID: "CVE-2014-fake-1",
Namespace: "debian:distro:debian:8",
},
Package: pkg.Package{
ID: pkg.ID(uuid.NewString()),
Name: "the-package",
Version: "v0.1",
Type: syftPkg.RpmPkg,
},
Details: match.Details{
{
Type: match.ExactDirectMatch,
},
},
})
my_metadataProvider := db.NewVulnerabilityMetadataProvider(newFakeMetaProvider())
type args struct {
scanResults *models.PresenterConfig
severity vulnerability.Severity
}
tests := []struct {
name string
args args
want bool
}{
{
name: "No severity set",
args: args{
scanResults: &models.PresenterConfig{
Matches: match.NewMatches(),
MetadataProvider: nil,
},
severity: vulnerability.UnknownSeverity,
},
want: false,
},
{
name: "No MetadataProvider",
args: args{
scanResults: &models.PresenterConfig{
Matches: my_matches,
MetadataProvider: nil,
},
severity: vulnerability.MediumSeverity,
},
want: false,
},
{
name: "Severity higher than vulnerability",
args: args{
scanResults: &models.PresenterConfig{
Matches: my_matches,
MetadataProvider: my_metadataProvider,
},
severity: vulnerability.HighSeverity,
},
want: false,
},
{
name: "Severity equal to vulnerability",
args: args{
scanResults: &models.PresenterConfig{
Matches: my_matches,
MetadataProvider: my_metadataProvider,
},
severity: vulnerability.MediumSeverity,
},
want: true,
},
{
name: "Fail severity below found vulnerability",
args: args{
scanResults: &models.PresenterConfig{
Matches: my_matches,
MetadataProvider: my_metadataProvider,
},
severity: vulnerability.LowSeverity,
},
want: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := ExceedsSeverityThreshold(tt.args.scanResults, tt.args.severity)
assert.Equal(t, tt.want, got)
})
}
}