From 5ff586cb3a12c6f60fa79164b6a3d3e74461d6f4 Mon Sep 17 00:00:00 2001 From: Darren <75614232+dmurray-lacework@users.noreply.github.com> Date: Mon, 11 Jul 2022 17:47:20 +0100 Subject: [PATCH] feat(cli): include status in vuln ctr scan assesment output (#853) * feat(cli): include status in vuln ctr scan assesment output * fix(cli): fix regex for vulnerability exceptions create * test: updated vulnerability tests * test: disable TestEventCommandListSeverityWithJsonFlag * test: renable events test Signed-off-by: Darren Murray --- api/vulnerabilities_container.go | 1 + cli/cmd/vuln_container.go | 5 ++- cli/cmd/vulnerability_exceptions_test.go | 46 ++++++++++++++++++++++++ cli/cmd/vulnerability_test.go | 6 +++- cli/cmd/vulnerabilty_exceptions.go | 14 +++++--- 5 files changed, 65 insertions(+), 7 deletions(-) diff --git a/api/vulnerabilities_container.go b/api/vulnerabilities_container.go index 51bcdd7e2..70ea28e06 100644 --- a/api/vulnerabilities_container.go +++ b/api/vulnerabilities_container.go @@ -316,6 +316,7 @@ type ContainerVulnerability struct { Link string `json:"link"` FixVersion string `json:"fix_version"` Metadata map[string]interface{} `json:"metadata"` + Status string `json:"status"` } // traverseMetadata will try to extract an interface from the nested tree of key diff --git a/cli/cmd/vuln_container.go b/cli/cmd/vuln_container.go index 05b1e4dcc..b57292931 100644 --- a/cli/cmd/vuln_container.go +++ b/cli/cmd/vuln_container.go @@ -626,7 +626,7 @@ func buildVulnerabilityDetailsReportTable(details vulnerabilityDetailsReport) st report.WriteString( renderCustomTable( []string{"CVE ID", "Severity", "Package", "Current Version", - "Fix Version", "Introduced in Layer"}, + "Fix Version", "Introduced in Layer", "Status"}, vulnImageTable, tableFunc(func(t *tablewriter.Table) { t.SetBorder(false) @@ -696,6 +696,7 @@ type vulnTable struct { CreatedBy string CVSSv2Score float64 CVSSv3Score float64 + Status string } type filteredImageTable struct { @@ -818,6 +819,7 @@ func filterVulContainerImageLayers(image *api.VulnContainerImage) filteredImageT CreatedBy: createdBy, CVSSv2Score: vul.CVSSv2Score(), CVSSv3Score: vul.CVSSv3Score(), + Status: vul.Status, }) filteredPkg.Vulnerabilities = append(filteredPkg.Vulnerabilities, vul) @@ -870,6 +872,7 @@ func vulContainerImageLayersToTable(imageTable filteredImageTable) [][]string { vuln.CurrentVersion, vuln.FixVersion, vuln.CreatedBy, + vuln.Status, }) } diff --git a/cli/cmd/vulnerability_exceptions_test.go b/cli/cmd/vulnerability_exceptions_test.go index aef8e4484..0a6885e53 100644 --- a/cli/cmd/vulnerability_exceptions_test.go +++ b/cli/cmd/vulnerability_exceptions_test.go @@ -18,6 +18,7 @@ package cmd import ( + "regexp" "testing" "github.com/stretchr/testify/assert" @@ -30,6 +31,51 @@ func TestBuildVulnerabilityException(t *testing.T) { assert.Equal(t, vulnExceptionPropertiesTable, vulnPropertiesOutput) } +func TestCVEValidate(t *testing.T) { + cveRegEx, _ := regexp.Compile(CveRegex) + alasRegEx, _ := regexp.Compile(AlasRegex) + + cveTableTest := []struct { + Name string + Input string + Regex *regexp.Regexp + Expected bool + }{{ + Name: "CVE Valid", + Input: "CVE-2022-28948", + Regex: cveRegEx, + Expected: true, + }, { + Name: "CVE Invalid", + Input: "CV-202-28948", + Regex: cveRegEx, + Expected: false, + }, { + Name: "ALAS Valid", + Input: "ALAS-2022-1788", + Regex: alasRegEx, + Expected: true, + }, { + Name: "ALAS Valid", + Input: "ALAS2-2022-1802", + Regex: alasRegEx, + Expected: true, + }, + { + Name: "ALAS Invalid", + Input: "ALA-2022-1788", + Regex: alasRegEx, + Expected: false, + }, + } + for _, test := range cveTableTest { + t.Run(test.Name, func(t *testing.T) { + result := test.Regex.MatchString(test.Input) + assert.Equal(t, result, test.Expected) + }) + } +} + var ( mockVulnException = api.VulnerabilityException{ Enabled: 1, diff --git a/cli/cmd/vulnerability_test.go b/cli/cmd/vulnerability_test.go index 803656464..183c7fa33 100644 --- a/cli/cmd/vulnerability_test.go +++ b/cli/cmd/vulnerability_test.go @@ -174,7 +174,8 @@ func TestBuildVulnContainerAssessmentReportsWithVulnerabilitiesPackagesViewWithF } }, "name": "CVE-2021-36159", - "severity": "critical" + "severity": "critical", + "status": "Vulnerable" } ] } @@ -226,6 +227,7 @@ func mockVulnerabilityAssessment() *api.VulnContainerAssessment { "description": "", "fix_version": "2.10.6-r0", "link": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-30139", + "status": "Vulnerable", "metadata": { "NVD": { "CVSSv2": { @@ -248,6 +250,7 @@ func mockVulnerabilityAssessment() *api.VulnContainerAssessment { "description": "", "fix_version": "2.10.7-r0", "link": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-36159", + "status": "Vulnerable", "metadata": { "NVD": { "CVSSv2": { @@ -277,6 +280,7 @@ func mockVulnerabilityAssessment() *api.VulnContainerAssessment { "description": "", "fix_version": "1.1.24-r10", "link": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-28928", + "status": "Vulnerable", "metadata": { "NVD": { "CVSSv2": { diff --git a/cli/cmd/vulnerabilty_exceptions.go b/cli/cmd/vulnerabilty_exceptions.go index 07f575b89..3195f983f 100644 --- a/cli/cmd/vulnerabilty_exceptions.go +++ b/cli/cmd/vulnerabilty_exceptions.go @@ -32,6 +32,9 @@ import ( "github.com/spf13/cobra" ) +const CveRegex = `(?i)CVE-\d{4}-\d{4,7}` +const AlasRegex = `(?i)ALAS(2?)-\d{4}-\d{3,7}` + var ( // vulnerability-exceptions command is used to manage lacework vulnerability exceptions vulnerabilityExceptionCommand = &cobra.Command{ @@ -343,17 +346,18 @@ func transformVulnerabilityExceptionPackages(packages string) []api.Vulnerabilit func validateCveFormat() survey.Validator { return func(val interface{}) error { - cveRegEx, _ := regexp.Compile(`(?i)CVE-\d{4}-\d{4,7}`) + cveRegEx, _ := regexp.Compile(CveRegex) + alasRegEx, _ := regexp.Compile(AlasRegex) if list, ok := val.([]core.OptionAnswer); ok { for _, i := range list { - if !cveRegEx.MatchString(i.Value) { - return fmt.Errorf("CVE format is invalid. Please format corretly eg: CVE-2014-0001") + if !cveRegEx.MatchString(i.Value) && !alasRegEx.MatchString(i.Value) { + return fmt.Errorf("CVE format is invalid. Please format corretly eg: CVE-2014-0001, ALAS2-2022-1788") } } } else { value := val.(string) - if !cveRegEx.MatchString(value) { - return fmt.Errorf("CVE format is invalid. Please format corretly eg: CVE-2014-0001") + if !cveRegEx.MatchString(value) && !alasRegEx.MatchString(value) { + return fmt.Errorf("CVE format is invalid. Please format corretly eg: CVE-2014-0001, ALAS2-2022-1788") } } return nil