Skip to content
This repository has been archived by the owner on Oct 14, 2024. It is now read-only.

Commit

Permalink
fix: enrich vulnerability instead of using first
Browse files Browse the repository at this point in the history
  • Loading branch information
paralta committed Jul 31, 2024
1 parent 85c6284 commit 7dd5d97
Show file tree
Hide file tree
Showing 7 changed files with 217 additions and 735 deletions.
30 changes: 12 additions & 18 deletions cli/presenter/apimodel.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,28 +60,22 @@ func ConvertSBOMResultToPackages(result *sbom.Result) []apitypes.Package {
func ConvertVulnResultToVulnerabilities(result *vulnerabilities.Result) []apitypes.Vulnerability {
vuls := []apitypes.Vulnerability{}

if result == nil || result.MergedVulnerabilitiesByKey == nil {
if result == nil || result.VulnerabilitiesByKey == nil {
return vuls
}

for _, vulCandidates := range result.MergedVulnerabilitiesByKey {
if len(vulCandidates) < 1 {
continue
}

vulCandidate := vulCandidates[0]

for _, vulCandidate := range result.VulnerabilitiesByKey {
vul := apitypes.Vulnerability{
Cvss: ConvertVulnCvssToAPIModel(vulCandidate.Vulnerability.CVSS),
Description: to.Ptr(vulCandidate.Vulnerability.Description),
Distro: ConvertVulnDistroToAPIModel(vulCandidate.Vulnerability.Distro),
Fix: ConvertVulnFixToAPIModel(vulCandidate.Vulnerability.Fix),
LayerId: to.Ptr(vulCandidate.Vulnerability.LayerID),
Links: to.Ptr(vulCandidate.Vulnerability.Links),
Package: ConvertVulnPackageToAPIModel(vulCandidate.Vulnerability.Package),
Path: to.Ptr(vulCandidate.Vulnerability.Path),
Severity: ConvertVulnSeverityToAPIModel(vulCandidate.Vulnerability.Severity),
VulnerabilityName: to.Ptr(vulCandidate.Vulnerability.ID),
Cvss: ConvertVulnCvssToAPIModel(vulCandidate.CVSS),
Description: to.Ptr(vulCandidate.Description),
Distro: ConvertVulnDistroToAPIModel(vulCandidate.Distro),
Fix: ConvertVulnFixToAPIModel(vulCandidate.Fix),
LayerId: to.Ptr(vulCandidate.LayerID),
Links: to.Ptr(vulCandidate.Links),
Package: ConvertVulnPackageToAPIModel(vulCandidate.Package),
Path: to.Ptr(vulCandidate.Path),
Severity: ConvertVulnSeverityToAPIModel(vulCandidate.Severity),
VulnerabilityName: to.Ptr(vulCandidate.ID),
}
vuls = append(vuls, vul)
}
Expand Down
172 changes: 81 additions & 91 deletions cli/presenter/apimodel_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,108 +161,98 @@ func Test_ConvertVulnResultToVulnerabilities(t *testing.T) {
name: "Vuls",
args: args{
result: &vulnerabilities.Result{
MergedVulnerabilitiesByKey: map[vulnerabilities.VulnerabilityKey][]vulnerabilities.MergedVulnerability{
VulnerabilitiesByKey: map[vulnerabilities.VulnerabilityKey]vulnerabilities.Vulnerability{
"vulkey1": {
{
ID: "id1",
Vulnerability: vulnerabilities.Vulnerability{
ID: "CVE-test-test-foo",
Description: "testbleed",
Links: []string{"link1", "link2"},
Distro: vulnerabilities.Distro{
Name: "distro1",
Version: "distrov1",
IDLike: []string{"IDLike1", "IDLike2"},
},
CVSS: []vulnerabilities.CVSS{
{
Version: "v1",
Vector: "vector1",
Metrics: vulnerabilities.CvssMetrics{
BaseScore: 1,
ExploitabilityScore: nil,
ImpactScore: nil,
},
},
{
Version: "v2",
Vector: "vector2",
Metrics: vulnerabilities.CvssMetrics{
BaseScore: 2,
ExploitabilityScore: to.Ptr(2.1),
ImpactScore: to.Ptr(2.2),
},
},
},
Fix: vulnerabilities.Fix{
Versions: []string{"fv1", "fv2"},
State: "fixed",
ID: "CVE-test-test-foo",
Description: "testbleed",
Links: []string{"link1", "link2"},
Distro: vulnerabilities.Distro{
Name: "distro1",
Version: "distrov1",
IDLike: []string{"IDLike1", "IDLike2"},
},
CVSS: []vulnerabilities.CVSS{
{
Version: "v1",
Vector: "vector1",
Metrics: vulnerabilities.CvssMetrics{
BaseScore: 1,
ExploitabilityScore: nil,
ImpactScore: nil,
},
Severity: string(apitypes.CRITICAL),
Package: vulnerabilities.Package{
Name: "package1",
Version: "pv1",
Type: "pt1",
Language: "pl1",
Licenses: []string{"plic1", "plic2"},
CPEs: []string{"cpe1", "cpe2"},
PURL: "purl1",
},
{
Version: "v2",
Vector: "vector2",
Metrics: vulnerabilities.CvssMetrics{
BaseScore: 2,
ExploitabilityScore: to.Ptr(2.1),
ImpactScore: to.Ptr(2.2),
},
LayerID: "lid1",
Path: "path1",
},
},
Fix: vulnerabilities.Fix{
Versions: []string{"fv1", "fv2"},
State: "fixed",
},
Severity: string(apitypes.CRITICAL),
Package: vulnerabilities.Package{
Name: "package1",
Version: "pv1",
Type: "pt1",
Language: "pl1",
Licenses: []string{"plic1", "plic2"},
CPEs: []string{"cpe1", "cpe2"},
PURL: "purl1",
},
LayerID: "lid1",
Path: "path1",
},
"vulkey2": {
{
ID: "id2",
Vulnerability: vulnerabilities.Vulnerability{
ID: "CVE-test-test-bar",
Description: "solartest",
Links: []string{"link3", "link4"},
Distro: vulnerabilities.Distro{
Name: "distro2",
Version: "distrov2",
IDLike: []string{"IDLike3", "IDLike4"},
},
CVSS: []vulnerabilities.CVSS{
{
Version: "v3",
Vector: "vector3",
Metrics: vulnerabilities.CvssMetrics{
BaseScore: 3,
ExploitabilityScore: nil,
ImpactScore: nil,
},
},
{
Version: "v4",
Vector: "vector4",
Metrics: vulnerabilities.CvssMetrics{
BaseScore: 4,
ExploitabilityScore: to.Ptr(4.1),
ImpactScore: to.Ptr(4.2),
},
},
},
Fix: vulnerabilities.Fix{
Versions: []string{"fv3", "fv4"},
State: "not-fixed",
ID: "CVE-test-test-bar",
Description: "solartest",
Links: []string{"link3", "link4"},
Distro: vulnerabilities.Distro{
Name: "distro2",
Version: "distrov2",
IDLike: []string{"IDLike3", "IDLike4"},
},
CVSS: []vulnerabilities.CVSS{
{
Version: "v3",
Vector: "vector3",
Metrics: vulnerabilities.CvssMetrics{
BaseScore: 3,
ExploitabilityScore: nil,
ImpactScore: nil,
},
Severity: string(apitypes.HIGH),
Package: vulnerabilities.Package{
Name: "package2",
Version: "pv2",
Type: "pt2",
Language: "pl2",
Licenses: []string{"plic3", "plic4"},
CPEs: []string{"cpe3", "cpe4"},
PURL: "purl2",
},
{
Version: "v4",
Vector: "vector4",
Metrics: vulnerabilities.CvssMetrics{
BaseScore: 4,
ExploitabilityScore: to.Ptr(4.1),
ImpactScore: to.Ptr(4.2),
},
LayerID: "lid2",
Path: "path2",
},
},
Fix: vulnerabilities.Fix{
Versions: []string{"fv3", "fv4"},
State: "not-fixed",
},
Severity: string(apitypes.HIGH),
Package: vulnerabilities.Package{
Name: "package2",
Version: "pv2",
Type: "pt2",
Language: "pl2",
Licenses: []string{"plic3", "plic4"},
CPEs: []string{"cpe3", "cpe4"},
PURL: "purl2",
},
LayerID: "lid2",
Path: "path2",
},
"vulkey3": {},
},
Expand Down
11 changes: 4 additions & 7 deletions scanner/families/exploits/family.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,17 +81,14 @@ func (e Exploits) Run(ctx context.Context, res *families.Results) (*types.Result
}

// create a comma separated representation of cveIDs array, as an input for the exploits scanners.
func getCVEIDsFromVulnerabilitiesResults(vulnerabilities *vulnerabilitytypes.Result) string {
if vulnerabilities == nil {
func getCVEIDsFromVulnerabilitiesResults(result *vulnerabilitytypes.Result) string {
if result == nil {
return ""
}

cvesMap := make(map[string]bool)

for _, mergedVulnerabilities := range vulnerabilities.MergedVulnerabilitiesByKey {
for _, vulnerability := range mergedVulnerabilities {
cvesMap[vulnerability.Vulnerability.ID] = true
}
for _, vulnerability := range result.VulnerabilitiesByKey {
cvesMap[vulnerability.ID] = true
}

cves := strings.Join(to.Keys(cvesMap), ",")
Expand Down
50 changes: 11 additions & 39 deletions scanner/families/exploits/family_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ func Test_getCVEIDsFromVulnerabilitiesResults(t *testing.T) {
wantCves: "",
},
{
name: "nil MergedVulnerabilitiesByKey",
name: "nil VulnerabilitiesByKey",
args: args{
vulnResults: &vulnerabilitytypes.Result{
MergedVulnerabilitiesByKey: nil,
VulnerabilitiesByKey: nil,
},
},
wantCves: "",
Expand All @@ -52,7 +52,7 @@ func Test_getCVEIDsFromVulnerabilitiesResults(t *testing.T) {
name: "no vulnerabilities",
args: args{
vulnResults: &vulnerabilitytypes.Result{
MergedVulnerabilitiesByKey: map[vulnerabilitytypes.VulnerabilityKey][]vulnerabilitytypes.MergedVulnerability{},
VulnerabilitiesByKey: map[vulnerabilitytypes.VulnerabilityKey]vulnerabilitytypes.Vulnerability{},
},
},
wantCves: "",
Expand All @@ -61,55 +61,27 @@ func Test_getCVEIDsFromVulnerabilitiesResults(t *testing.T) {
name: "sanity",
args: args{
vulnResults: &vulnerabilitytypes.Result{
MergedVulnerabilitiesByKey: map[vulnerabilitytypes.VulnerabilityKey][]vulnerabilitytypes.MergedVulnerability{
"vul1": {
{
Vulnerability: vulnerabilitytypes.Vulnerability{ID: "cve1"},
},
{
Vulnerability: vulnerabilitytypes.Vulnerability{ID: "cve2"},
},
},
"vul2": {
{
Vulnerability: vulnerabilitytypes.Vulnerability{ID: "cve3"},
},
{
Vulnerability: vulnerabilitytypes.Vulnerability{ID: "cve4"},
},
},
VulnerabilitiesByKey: map[vulnerabilitytypes.VulnerabilityKey]vulnerabilitytypes.Vulnerability{
"vul1": {ID: "cve1"},
"vul2": {ID: "cve3"},
},
Source: vulnerabilitytypes.Source{},
},
},
wantCves: "cve1,cve2,cve3,cve4",
wantCves: "cve1,cve3",
},
{
name: "same cve id in different vulnerabilities",
args: args{
vulnResults: &vulnerabilitytypes.Result{
MergedVulnerabilitiesByKey: map[vulnerabilitytypes.VulnerabilityKey][]vulnerabilitytypes.MergedVulnerability{
"vul1": {
{
Vulnerability: vulnerabilitytypes.Vulnerability{ID: "cve1"},
},
{
Vulnerability: vulnerabilitytypes.Vulnerability{ID: "cve2"},
},
},
"vul2": {
{
Vulnerability: vulnerabilitytypes.Vulnerability{ID: "cve1"},
},
{
Vulnerability: vulnerabilitytypes.Vulnerability{ID: "cve4"},
},
},
VulnerabilitiesByKey: map[vulnerabilitytypes.VulnerabilityKey]vulnerabilitytypes.Vulnerability{
"vul1": {ID: "cve1"},
"vul2": {ID: "cve1"},
},
Source: vulnerabilitytypes.Source{},
},
},
wantCves: "cve1,cve2,cve4",
wantCves: "cve1",
},
}
for _, tt := range tests {
Expand Down
30 changes: 13 additions & 17 deletions scanner/families/vulnerabilities/types/result.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,14 @@ type Source struct {
}

type Result struct {
Metadata families.ScanMetadata `json:"Metadata"`
Source Source `json:"Source"`
MergedVulnerabilitiesByKey map[VulnerabilityKey][]MergedVulnerability `json:"MergedVulnerabilitiesByKey"`
Metadata families.ScanMetadata `json:"Metadata"`
Source Source `json:"Source"`
VulnerabilitiesByKey map[VulnerabilityKey]Vulnerability `json:"VulnerabilitiesByKey"`
}

func NewResult() *Result {
return &Result{
MergedVulnerabilitiesByKey: make(map[VulnerabilityKey][]MergedVulnerability),
VulnerabilitiesByKey: make(map[VulnerabilityKey]Vulnerability),
}
}

Expand Down Expand Up @@ -74,10 +74,10 @@ func (r *Result) GetSourceImageInfo() (*apitypes.ContainerImageInfo, error) {
return containerImageInfo, nil
}

// ToSlice returns MergedResults in a slice format and not by key.
func (r *Result) ToSlice() [][]MergedVulnerability {
ret := make([][]MergedVulnerability, 0)
for _, vulnerabilities := range r.MergedVulnerabilitiesByKey {
// ToSlice returns Result in a slice format and not by key.
func (r *Result) ToSlice() []Vulnerability {
ret := make([]Vulnerability, 0)
for _, vulnerabilities := range r.VulnerabilitiesByKey {
ret = append(ret, vulnerabilities)
}

Expand All @@ -92,19 +92,15 @@ func (r *Result) Merge(meta families.ScanInputMetadata, result *ScannerResult) {
return
}

otherVulnerabilityByKey := toVulnerabilityByKey(result.Vulnerabilities)
for _, vulnerability := range result.Vulnerabilities {
key := NewVulnerabilityKey(vulnerability)

// go over other vulnerabilities list
// 1. merge mutual vulnerabilities
// 2. add non mutual vulnerabilities
for key, otherVulnerability := range otherVulnerabilityByKey {
// look for other vulnerability key in the current merged vulnerabilities list
if mergedVulnerabilities, ok := r.MergedVulnerabilitiesByKey[key]; !ok {
// add non mutual vulnerability
if existingVulnerability, ok := r.VulnerabilitiesByKey[key]; !ok {
log.Debugf("Adding new vulnerability results from %v. key=%v", result.Scanner, key)
r.MergedVulnerabilitiesByKey[key] = []MergedVulnerability{*NewMergedVulnerability(otherVulnerability, result.Scanner)}
r.VulnerabilitiesByKey[key] = vulnerability
} else {
r.MergedVulnerabilitiesByKey[key] = handleVulnerabilityWithExistingKey(mergedVulnerabilities, otherVulnerability, result.Scanner)
r.VulnerabilitiesByKey[key] = handleVulnerabilityWithExistingKey(existingVulnerability, vulnerability)
}
}

Expand Down
Loading

0 comments on commit 7dd5d97

Please sign in to comment.