From 51241351d7fcb91442e9eec18c02a7a0bb4b8eb7 Mon Sep 17 00:00:00 2001 From: Tomasz Janiszewski Date: Tue, 22 Mar 2022 15:28:55 +0100 Subject: [PATCH] ROX-9470: Add CVSS and Fixable column to CVE report (#142) --- .../stackrox/jenkins/plugins/data/CVE.java | 24 +++++--- .../plugins/report/ReportGenerator.java | 28 +++++---- .../src/main/webapp/js/renderTables.js | 10 ++- .../plugins/report/ReportGeneratorTest.java | 61 ++++++++++++------- .../resources/report/jenkins.lts/cves.csv | 8 +-- .../resources/report/nginx.latest/cves.csv | 6 +- 6 files changed, 88 insertions(+), 49 deletions(-) diff --git a/stackrox-container-image-scanner/src/main/java/com/stackrox/jenkins/plugins/data/CVE.java b/stackrox-container-image-scanner/src/main/java/com/stackrox/jenkins/plugins/data/CVE.java index 8c945d70..afe626ba 100644 --- a/stackrox-container-image-scanner/src/main/java/com/stackrox/jenkins/plugins/data/CVE.java +++ b/stackrox-container-image-scanner/src/main/java/com/stackrox/jenkins/plugins/data/CVE.java @@ -1,26 +1,36 @@ package com.stackrox.jenkins.plugins.data; +import com.google.common.base.Strings; + +import com.stackrox.model.StorageEmbeddedVulnerability; + import lombok.AllArgsConstructor; import lombok.Data; -import com.stackrox.model.StorageEmbeddedVulnerability; +import javax.annotation.Nonnull; @Data @AllArgsConstructor public class CVE { + private final String id; + private final Float cvssScore; + private final String scoreType; private final String packageName; private final String packageVersion; - private final String severity; - private final String id; + private final boolean fixable; private final String link; + private final String severity; - public CVE(String packageName, String packageVersion, StorageEmbeddedVulnerability vulnerability) { + public CVE(String packageName, String packageVersion, @Nonnull StorageEmbeddedVulnerability vulnerability) { this( + vulnerability.getCve(), + vulnerability.getCvss(), + vulnerability.getScoreVersion() != null ? vulnerability.getScoreVersion().toString() : null, packageName, packageVersion, - SeverityUtil.prettySeverity(vulnerability.getSeverity()), - vulnerability.getCve(), - vulnerability.getLink() + !Strings.isNullOrEmpty(vulnerability.getFixedBy()), + vulnerability.getLink(), + SeverityUtil.prettySeverity(vulnerability.getSeverity()) ); } } diff --git a/stackrox-container-image-scanner/src/main/java/com/stackrox/jenkins/plugins/report/ReportGenerator.java b/stackrox-container-image-scanner/src/main/java/com/stackrox/jenkins/plugins/report/ReportGenerator.java index fd5d3ef9..3a84066e 100644 --- a/stackrox-container-image-scanner/src/main/java/com/stackrox/jenkins/plugins/report/ReportGenerator.java +++ b/stackrox-container-image-scanner/src/main/java/com/stackrox/jenkins/plugins/report/ReportGenerator.java @@ -1,27 +1,28 @@ package com.stackrox.jenkins.plugins.report; -import java.io.BufferedWriter; -import java.io.IOException; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.List; - import com.google.common.base.Strings; + +import com.stackrox.jenkins.plugins.data.CVE; +import com.stackrox.jenkins.plugins.data.ImageCheckResults; +import com.stackrox.jenkins.plugins.data.PolicyViolation; + import hudson.AbortException; import hudson.FilePath; import org.apache.commons.csv.CSVFormat; import org.apache.commons.csv.CSVPrinter; import org.apache.commons.csv.QuoteMode; -import com.stackrox.jenkins.plugins.data.CVE; -import com.stackrox.jenkins.plugins.data.ImageCheckResults; -import com.stackrox.jenkins.plugins.data.PolicyViolation; +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.List; public class ReportGenerator { - private static final String[] CVES_HEADER = {"COMPONENT", "VERSION", "CVE", "SEVERITY", "LINK"}; + private static final String[] CVES_HEADER = {"COMPONENT", "VERSION", "CVE", "FIXABLE", "SEVERITY", "CVSS SCORE", "SCORE TYPE", "LINK"}; private static final String[] VIOLATED_POLICIES_HEADER = {"POLICY", "SEVERITY", "DESCRIPTION", "VIOLATION", "REMEDIATION", "ENFORCED"}; private static final String CVES_FILENAME = "cves.csv"; private static final String POLICY_VIOLATIONS_FILENAME = "policyViolations.csv"; @@ -51,6 +52,9 @@ private static void generateReport(FilePath reportsDir, ImageCheckResults result cve.getPackageVersion(), cve.getId(), cve.getSeverity(), + cve.isFixable(), + cve.getCvssScore(), + cve.getScoreType(), cve.getLink() )); } diff --git a/stackrox-container-image-scanner/src/main/webapp/js/renderTables.js b/stackrox-container-image-scanner/src/main/webapp/js/renderTables.js index 89c96502..f1220eb8 100644 --- a/stackrox-container-image-scanner/src/main/webapp/js/renderTables.js +++ b/stackrox-container-image-scanner/src/main/webapp/js/renderTables.js @@ -14,10 +14,18 @@ function renderCVETable(tableId, cves) { } }, { title: 'SEVERITY', data : 'severity' }, + { title: 'CVSS SCORE', mData : function (data, type, dataToSet) { + if (data.cvssScore == 0) { + return `-` + } + return `${data.cvssScore} (${data.scoreType})`; + } + }, + { title: 'FIXABLE', data : 'fixable' }, ], columnDefs: [ { - targets: [0, 1, 2, 3], + targets: [0, 1, 2, 3, 4], render: function (source, type, val) { return `${source}`; } diff --git a/stackrox-container-image-scanner/src/test/java/com/stackrox/jenkins/plugins/report/ReportGeneratorTest.java b/stackrox-container-image-scanner/src/test/java/com/stackrox/jenkins/plugins/report/ReportGeneratorTest.java index b618349e..95cb0ead 100644 --- a/stackrox-container-image-scanner/src/test/java/com/stackrox/jenkins/plugins/report/ReportGeneratorTest.java +++ b/stackrox-container-image-scanner/src/test/java/com/stackrox/jenkins/plugins/report/ReportGeneratorTest.java @@ -1,5 +1,7 @@ package com.stackrox.jenkins.plugins.report; +import static com.stackrox.model.StorageEmbeddedVulnerabilityScoreVersion.V2; +import static com.stackrox.model.StorageEmbeddedVulnerabilityScoreVersion.V3; import static com.stackrox.model.StorageEnforcementAction.FAIL_BUILD_ENFORCEMENT; import static com.stackrox.model.StorageSeverity.HIGH_SEVERITY; import static com.stackrox.model.StorageSeverity.MEDIUM_SEVERITY; @@ -83,34 +85,49 @@ void testGenerateReportForResultsThrowsOnWriteException() throws IOException { void testGenerateReportForResultsWritesReportsForEveryImageInSeparatedDirectory() throws IOException { FilePath reportsDir = new FilePath(folder.toFile()); List results = ImmutableList.of( - new ImageCheckResults("jenkins:lts", ImmutableList.of( - new CVE("util-linux", "2.25.2-6", new StorageEmbeddedVulnerability() - .cve("CVE-2015-5224") - .severity(IMPORTANT_VULNERABILITY_SEVERITY) - .link("https://security-tracker.debian.org/tracker/CVE-2015-5224")), - new CVE("gcc-4.8", "4.8.4-1", new StorageEmbeddedVulnerability() - .cve("CVE-2017-11671") - .severity(MODERATE_VULNERABILITY_SEVERITY) - .link("https://security-tracker.debian.org/tracker/CVE-2017-11671")), - new CVE("bzip2", "1.0.6-7", new StorageEmbeddedVulnerability() - .cve("CVE-2016-3189") - .severity(LOW_VULNERABILITY_SEVERITY) - .link("https://security-tracker.debian.org/tracker/CVE-2016-3189") - .fixedBy("1.0.6-8")) - ), ImmutableList.of(new PolicyViolation(new StoragePolicy() - .name("Fixable Severity at least Important") - .description("Alert on deployments with fixable vulnerabilities with a Severity Rating at least Important") - .severity(HIGH_SEVERITY) - .enforcementActions(ImmutableList.of(FAIL_BUILD_ENFORCEMENT)) - .remediation("Use your package manager to update to a fixed version in future builds or speak with your security team to mitigate the vulnerabilities.") - , ""))), + new ImageCheckResults("jenkins:lts", + ImmutableList.of( + new CVE("util-linux", "2.25.2-6", new StorageEmbeddedVulnerability() + .cve("CVE-2015-5224") + .severity(IMPORTANT_VULNERABILITY_SEVERITY) + .cvss(9.8F) + .scoreVersion(V3) + .link("https://security-tracker.debian.org/tracker/CVE-2015-5224")), + new CVE("gcc-4.8", "4.8.4-1", new StorageEmbeddedVulnerability() + .cve("CVE-2017-11671") + .severity(MODERATE_VULNERABILITY_SEVERITY) + .cvss(4.0F) + .scoreVersion(V3) + .link("https://security-tracker.debian.org/tracker/CVE-2017-11671")), + new CVE("bzip2", "1.0.6-7", new StorageEmbeddedVulnerability() + .cve("CVE-2016-3189") + .severity(LOW_VULNERABILITY_SEVERITY) + .cvss(6.5F) + .scoreVersion(V3) + .link("https://security-tracker.debian.org/tracker/CVE-2016-3189") + .fixedBy("1.0.6-8")) + ), + ImmutableList.of( + new PolicyViolation(new StoragePolicy() + .name("Fixable Severity at least Important") + .description("Alert on deployments with fixable vulnerabilities with a Severity Rating at least Important") + .severity(HIGH_SEVERITY) + .enforcementActions(ImmutableList.of(FAIL_BUILD_ENFORCEMENT)) + .remediation("Use your package manager to update to a fixed version in future builds or speak with your security team to mitigate the vulnerabilities.") + , "") + )), new ImageCheckResults("nginx:latest", ImmutableList.of( new CVE("openssl", "1.1.1d-0+deb10u7", new StorageEmbeddedVulnerability() .cve("CVE-2007-6755") .severity(LOW_VULNERABILITY_SEVERITY) + .cvss(5.8F) + .scoreVersion(V2) .link("https://security-tracker.debian.org/tracker/CVE-2007-6755")), - new CVE(null, null, new StorageEmbeddedVulnerability())), + new CVE(null, null, new StorageEmbeddedVulnerability() + .cve("CVE-MISSING-DATA") + .scoreVersion(null) + .cvss(0F))), ImmutableList.of(new PolicyViolation(new StoragePolicy().name("Latest Tag") .description("") .severity(MEDIUM_SEVERITY), "Image has tag 'latest'"), diff --git a/stackrox-container-image-scanner/src/test/resources/report/jenkins.lts/cves.csv b/stackrox-container-image-scanner/src/test/resources/report/jenkins.lts/cves.csv index 3b6636e8..fd3c2e79 100644 --- a/stackrox-container-image-scanner/src/test/resources/report/jenkins.lts/cves.csv +++ b/stackrox-container-image-scanner/src/test/resources/report/jenkins.lts/cves.csv @@ -1,4 +1,4 @@ -COMPONENT,VERSION,CVE,SEVERITY,LINK -util-linux,2.25.2-6,CVE-2015-5224,IMPORTANT,https://security-tracker.debian.org/tracker/CVE-2015-5224 -gcc-4.8,4.8.4-1,CVE-2017-11671,MODERATE,https://security-tracker.debian.org/tracker/CVE-2017-11671 -bzip2,1.0.6-7,CVE-2016-3189,LOW,https://security-tracker.debian.org/tracker/CVE-2016-3189 +COMPONENT,VERSION,CVE,FIXABLE,SEVERITY,CVSS SCORE,SCORE TYPE,LINK +util-linux,2.25.2-6,CVE-2015-5224,IMPORTANT,false,9.8,V3,https://security-tracker.debian.org/tracker/CVE-2015-5224 +gcc-4.8,4.8.4-1,CVE-2017-11671,MODERATE,false,4.0,V3,https://security-tracker.debian.org/tracker/CVE-2017-11671 +bzip2,1.0.6-7,CVE-2016-3189,LOW,true,6.5,V3,https://security-tracker.debian.org/tracker/CVE-2016-3189 diff --git a/stackrox-container-image-scanner/src/test/resources/report/nginx.latest/cves.csv b/stackrox-container-image-scanner/src/test/resources/report/nginx.latest/cves.csv index 6022b8c4..66296acd 100644 --- a/stackrox-container-image-scanner/src/test/resources/report/nginx.latest/cves.csv +++ b/stackrox-container-image-scanner/src/test/resources/report/nginx.latest/cves.csv @@ -1,3 +1,3 @@ -COMPONENT,VERSION,CVE,SEVERITY,LINK -openssl,1.1.1d-0+deb10u7,CVE-2007-6755,LOW,https://security-tracker.debian.org/tracker/CVE-2007-6755 --,-,-,UNKNOWN,- +COMPONENT,VERSION,CVE,FIXABLE,SEVERITY,CVSS SCORE,SCORE TYPE,LINK +openssl,1.1.1d-0+deb10u7,CVE-2007-6755,LOW,false,5.8,V2,https://security-tracker.debian.org/tracker/CVE-2007-6755 +-,-,CVE-MISSING-DATA,UNKNOWN,false,0.0,-,-