Skip to content

Commit

Permalink
feat(cve): better distinguish max severity on an image (#918)
Browse files Browse the repository at this point in the history
Values returned now by GetCVESummaryForImage
// not scannable / error during scan  - max severity ""            - cve count 0   - Errors
// scannable no issues found          - max severity "NONE"        - cve count 0   - no Errors
// scannable issues found             - max severity from Scanner  - cve count >0  - no Errors

Before this change the max severity in case #1 and #2 was "UNKNOWN" which is also possible value
for case #3. To better distinguish them return different max severities.

This feature would be consumed by the UI.

Signed-off-by: Andrei Aaron <andaaron@cisco.com>
  • Loading branch information
andaaron authored Oct 24, 2022
1 parent 1d9c88c commit 92afd86
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 5 deletions.
16 changes: 14 additions & 2 deletions pkg/extensions/search/cve/cve.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,9 +177,13 @@ func (cveinfo BaseCveInfo) GetCVEListForImage(image string) (map[string]cvemodel
}

func (cveinfo BaseCveInfo) GetCVESummaryForImage(image string) (ImageCVESummary, error) {
// There are several cases, expected returned values below:
// not scannable / error during scan - max severity "" - cve count 0 - Errors
// scannable no issues found - max severity "NONE" - cve count 0 - no Errors
// scannable issues found - max severity from Scanner - cve count >0 - no Errors
imageCVESummary := ImageCVESummary{
Count: 0,
MaxSeverity: "UNKNOWN",
MaxSeverity: "",
}

isValidImage, err := cveinfo.Scanner.IsImageFormatScannable(image)
Expand All @@ -192,12 +196,20 @@ func (cveinfo BaseCveInfo) GetCVESummaryForImage(image string) (ImageCVESummary,
return imageCVESummary, err
}

imageCVESummary.Count = len(cveMap)

if imageCVESummary.Count == 0 {
imageCVESummary.MaxSeverity = "NONE"

return imageCVESummary, nil
}

imageCVESummary.MaxSeverity = "UNKNOWN"
for _, cve := range cveMap {
if cveinfo.Scanner.CompareSeverities(imageCVESummary.MaxSeverity, cve.Severity) > 0 {
imageCVESummary.MaxSeverity = cve.Severity
}
}
imageCVESummary.Count = len(cveMap)

return imageCVESummary, nil
}
Expand Down
66 changes: 63 additions & 3 deletions pkg/extensions/search/cve/cve_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -829,6 +829,20 @@ func TestCVEStruct(t *testing.T) {
}, nil
}

// Image with no CVEs
if repo == "repo4" { //nolint: goconst
return []ispec.Descriptor{
{
MediaType: "application/vnd.oci.image.manifest.v1+json",
Size: int64(0),
Annotations: map[string]string{
ispec.AnnotationRefName: "1.0.0",
},
Digest: godigest.FromString("abc"),
},
}, nil
}

// By default the image is not found
return nil, errors.ErrRepoNotFound
},
Expand Down Expand Up @@ -870,6 +884,17 @@ func TestCVEStruct(t *testing.T) {
}, nil
}

// Image with no vulnerabilities, repo3 is for tests on missing images
if repo == "repo4" { //nolint: goconst
return []common.TagInfo{
{
Name: "1.0.0",
Digest: godigest.FromString("abc"),
Timestamp: time.Date(2009, 1, 1, 12, 0, 0, 0, time.UTC),
},
}, nil
}

// By default do not return any tags
return []common.TagInfo{}, errors.ErrRepoNotFound
},
Expand Down Expand Up @@ -900,6 +925,19 @@ func TestCVEStruct(t *testing.T) {
}, nil
}

// Image with no CVEs
if imageDir == "repo4" { //nolint: goconst
return ispec.Manifest{
Layers: []ispec.Descriptor{
{
MediaType: string(ispec.MediaTypeImageLayer),
Size: 0,
Digest: godigest.Digest(""),
},
},
}, nil
}

return ispec.Manifest{}, errors.ErrBlobNotFound
},
}
Expand Down Expand Up @@ -1054,13 +1092,19 @@ func TestCVEStruct(t *testing.T) {
cveSummary, err = cveInfo.GetCVESummaryForImage("repo2:1.0.0")
So(err, ShouldEqual, errors.ErrScanNotSupported)
So(cveSummary.Count, ShouldEqual, 0)
So(cveSummary.MaxSeverity, ShouldEqual, "UNKNOWN")
So(cveSummary.MaxSeverity, ShouldEqual, "")

// Image is not found
cveSummary, err = cveInfo.GetCVESummaryForImage("repo3:1.0.0")
So(err, ShouldEqual, errors.ErrRepoNotFound)
So(cveSummary.Count, ShouldEqual, 0)
So(cveSummary.MaxSeverity, ShouldEqual, "UNKNOWN")
So(cveSummary.MaxSeverity, ShouldEqual, "")

// Image has no vulnerabilities
cveSummary, err = cveInfo.GetCVESummaryForImage("repo4:1.0.0")
So(err, ShouldBeNil)
So(cveSummary.Count, ShouldEqual, 0)
So(cveSummary.MaxSeverity, ShouldEqual, "NONE")
})

Convey("Test GetCVEListForImage", func() {
Expand Down Expand Up @@ -1104,6 +1148,11 @@ func TestCVEStruct(t *testing.T) {
cveMap, err = cveInfo.GetCVEListForImage("repo3:1.0.0")
So(err, ShouldEqual, errors.ErrRepoNotFound)
So(len(cveMap), ShouldEqual, 0)

// Image has no vulnerabilities
cveMap, err = cveInfo.GetCVEListForImage("repo4:1.0.0")
So(err, ShouldBeNil)
So(len(cveMap), ShouldEqual, 0)
})

Convey("Test GetImageListWithCVEFixed", func() {
Expand Down Expand Up @@ -1139,6 +1188,12 @@ func TestCVEStruct(t *testing.T) {
tagList, err = cveInfo.GetImageListWithCVEFixed("repo3", "CVE101")
So(err, ShouldEqual, errors.ErrRepoNotFound)
So(len(tagList), ShouldEqual, 0)

// Image has no vulnerabilities
tagList, err = cveInfo.GetImageListWithCVEFixed("repo4", "CVE101")
So(err, ShouldBeNil)
So(len(tagList), ShouldEqual, 1)
So(tagList[0].Name, ShouldEqual, "1.0.0")
})

Convey("Test GetImageListForCVE", func() {
Expand Down Expand Up @@ -1175,6 +1230,11 @@ func TestCVEStruct(t *testing.T) {
imageInfoByCveList, err = cveInfo.GetImageListForCVE("repo3", "CVE101")
So(err, ShouldEqual, errors.ErrRepoNotFound)
So(len(imageInfoByCveList), ShouldEqual, 0)

// Image/repo is not vulnerable
imageInfoByCveList, err = cveInfo.GetImageListForCVE("repo4", "CVE101")
So(err, ShouldBeNil)
So(len(imageInfoByCveList), ShouldEqual, 0)
})

Convey("Test errors while scanning", func() {
Expand All @@ -1190,7 +1250,7 @@ func TestCVEStruct(t *testing.T) {
cveSummary, err := cveInfo.GetCVESummaryForImage("repo1:0.1.0")
So(err, ShouldNotBeNil)
So(cveSummary.Count, ShouldEqual, 0)
So(cveSummary.MaxSeverity, ShouldEqual, "UNKNOWN")
So(cveSummary.MaxSeverity, ShouldEqual, "")

cveMap, err := cveInfo.GetCVEListForImage("repo1:0.1.0")
So(err, ShouldNotBeNil)
Expand Down

0 comments on commit 92afd86

Please sign in to comment.