From 22f17cb4a11f0d45aad5810f4bc86dd30674916d Mon Sep 17 00:00:00 2001 From: Ruben Romero Montes Date: Tue, 16 Apr 2024 21:21:43 +0200 Subject: [PATCH] feat!: adapt to osv metrics (#332) Signed-off-by: Ruben Romero Montes --- pom.xml | 6 + .../osvnvd/OsvNvdResponseHandler.java | 64 ++-- .../__files/osvnvd/maven_report.json | 323 ++++++++---------- 3 files changed, 183 insertions(+), 210 deletions(-) diff --git a/pom.xml b/pom.xml index 8d655932..ce440fb8 100644 --- a/pom.xml +++ b/pom.xml @@ -54,6 +54,7 @@ 1.1.9.1 2.70.0 3.4.2 + 1.4.2 v20.9.0 @@ -198,6 +199,11 @@ sentry ${sentry.version} + + us.springett + cvss-calculator + ${cvss-calculator.version} + org.apache.camel.quarkus camel-quarkus-junit5 diff --git a/src/main/java/com/redhat/exhort/integration/providers/osvnvd/OsvNvdResponseHandler.java b/src/main/java/com/redhat/exhort/integration/providers/osvnvd/OsvNvdResponseHandler.java index 842874ad..8778bf3f 100644 --- a/src/main/java/com/redhat/exhort/integration/providers/osvnvd/OsvNvdResponseHandler.java +++ b/src/main/java/com/redhat/exhort/integration/providers/osvnvd/OsvNvdResponseHandler.java @@ -21,6 +21,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -46,6 +47,7 @@ import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; +import us.springett.cvss.Cvss; @ApplicationScoped @RegisterForReflection @@ -90,9 +92,9 @@ private List toIssues(String ref, ArrayNode response) { if (issue.getTitle() == null || issue.getTitle().isEmpty()) { issue.title(getTextValue(data, "description")); } - var metrics = data.get("metrics"); - if (metrics != null) { - setMetrics(metrics, issue); + var severity = data.get("severity"); + if (severity != null) { + setSeverity(severity, issue); } var affected = data.get("affected"); if (affected != null) { @@ -105,30 +107,37 @@ private List toIssues(String ref, ArrayNode response) { return issues; } - // Parse only V3.1, V3.0 and V2 CVSS vectors - private void setMetrics(JsonNode metrics, Issue issue) { - ArrayNode metricsNode = null; - if (metrics.has("cvssMetricV31")) { - metricsNode = (ArrayNode) metrics.get("cvssMetricV31"); - } else if (metrics.has("cvssMetricV30")) { - metricsNode = (ArrayNode) metrics.get("cvssMetricV30"); - } else if (metrics.has("cvssMetricV2")) { - metricsNode = (ArrayNode) metrics.get("cvssMetricV2"); + // Prefer V3.1 and V3.0 over V2 CVSS vectors + private void setSeverity(JsonNode severity, Issue issue) { + Map severities = new HashMap<>(); + + severity.forEach( + metricNode -> { + var vector = metricNode.get("score").asText(); + var type = metricNode.get("type").asText(); + severities.put(type, vector); + }); + var cvss = severities.get("CVSS_V3"); + if (cvss != null) { + setCvssData(issue, cvss); + } else { + cvss = severities.get("CVSS_V2"); + if (cvss != null) { + setCvssData(issue, cvss); + } } - if (metricsNode == null) { + } + + private void setCvssData(Issue issue, String vector) { + if (issue.getCvss() != null) { return; } - metricsNode.forEach( - metricNode -> { - if ("Primary".equalsIgnoreCase(getTextValue(metricNode, "type"))) { - var cvssData = (JsonNode) metricNode.get("cvssData"); - var score = getFloatValue(cvssData, "baseScore"); - issue - .cvssScore(score) - .cvss(CvssParser.fromVectorString(getTextValue(cvssData, "vectorString"))) - .severity(SeverityUtils.fromScore(score)); - } - }); + var cvss = Cvss.fromVector(vector); + var score = Double.valueOf(cvss.calculateScore().getBaseScore()).floatValue(); + issue + .cvssScore(score) + .cvss(CvssParser.fromVectorString(vector)) + .severity(SeverityUtils.fromScore(score)); } private Remediation getRemediation(ArrayNode affected) { @@ -160,11 +169,4 @@ private String getTextValue(JsonNode node, String key) { } return null; } - - private Float getFloatValue(JsonNode node, String key) { - if (node.has(key)) { - return node.get(key).floatValue(); - } - return null; - } } diff --git a/src/test/resources/__files/osvnvd/maven_report.json b/src/test/resources/__files/osvnvd/maven_report.json index 778258be..ed719429 100644 --- a/src/test/resources/__files/osvnvd/maven_report.json +++ b/src/test/resources/__files/osvnvd/maven_report.json @@ -24,7 +24,14 @@ "ranges": [ { "type": "ECOSYSTEM", - "events": [{ "introduced": "42.2.0" }, { "fixed": "42.2.27" }] + "events": [ + { + "introduced": "42.2.0" + }, + { + "fixed": "42.2.27" + } + ] } ], "versions": [ @@ -120,7 +127,14 @@ "ranges": [ { "type": "ECOSYSTEM", - "events": [{ "introduced": "42.3.0" }, { "fixed": "42.3.8" }] + "events": [ + { + "introduced": "42.3.0" + }, + { + "fixed": "42.3.8" + } + ] } ], "versions": [ @@ -143,10 +157,21 @@ "ranges": [ { "type": "ECOSYSTEM", - "events": [{ "introduced": "42.4.0" }, { "fixed": "42.4.3" }] + "events": [ + { + "introduced": "42.4.0" + }, + { + "fixed": "42.4.3" + } + ] } ], - "versions": ["42.4.0", "42.4.1", "42.4.2"] + "versions": [ + "42.4.0", + "42.4.1", + "42.4.2" + ] }, { "package": { @@ -157,61 +182,34 @@ "ranges": [ { "type": "ECOSYSTEM", - "events": [{ "introduced": "42.5.0" }, { "fixed": "42.5.1" }] + "events": [ + { + "introduced": "42.5.0" + }, + { + "fixed": "42.5.1" + } + ] } ], - "versions": ["42.5.0"] + "versions": [ + "42.5.0" + ] } ], - "metrics": { - "cvssMetricV31": [ - { - "source": "nvd@nist.gov", - "type": "Primary", - "cvssData": { - "version": "3.1", - "vectorString": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N", - "attackVector": "LOCAL", - "attackComplexity": "LOW", - "privilegesRequired": "LOW", - "userInteraction": "NONE", - "scope": "UNCHANGED", - "confidentialityImpact": "HIGH", - "integrityImpact": "NONE", - "availabilityImpact": "NONE", - "baseScore": 5.5, - "baseSeverity": "MEDIUM" - }, - "exploitabilityScore": 1.8, - "impactScore": 3.6 - }, - { - "source": "security-advisories@github.com", - "type": "Secondary", - "cvssData": { - "version": "3.1", - "vectorString": "CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:H/I:N/A:N", - "attackVector": "LOCAL", - "attackComplexity": "HIGH", - "privilegesRequired": "LOW", - "userInteraction": "NONE", - "scope": "UNCHANGED", - "confidentialityImpact": "HIGH", - "integrityImpact": "NONE", - "availabilityImpact": "NONE", - "baseScore": 4.7, - "baseSeverity": "MEDIUM" - }, - "exploitabilityScore": 1.0, - "impactScore": 3.6 - } - ] - } + "severity": [ + { + "type": "CVSS_V3", + "score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N" + } + ] } ], "pkg:maven/com.fasterxml.jackson.core/jackson-databind@2.13.1?type=jar": [ { - "aliases": ["GHSA-57j2-w4cx-62h2"], + "aliases": [ + "GHSA-57j2-w4cx-62h2" + ], "cveId": "CVE-2020-36518", "created": "2024-01-15T21:37:47.413+00:00", "summary": "Deeply nested json in jackson-databind", @@ -226,10 +224,21 @@ "ranges": [ { "type": "ECOSYSTEM", - "events": [{ "introduced": "2.13.0" }, { "fixed": "2.13.2.1" }] + "events": [ + { + "introduced": "2.13.0" + }, + { + "fixed": "2.13.2.1" + } + ] } ], - "versions": ["2.13.0", "2.13.1", "2.13.2"] + "versions": [ + "2.13.0", + "2.13.1", + "2.13.2" + ] }, { "package": { @@ -240,7 +249,14 @@ "ranges": [ { "type": "ECOSYSTEM", - "events": [{ "introduced": "0" }, { "fixed": "2.12.6.1" }] + "events": [ + { + "introduced": "0" + }, + { + "fixed": "2.12.6.1" + } + ] } ], "versions": [ @@ -407,33 +423,17 @@ ] } ], - "metrics": { - "cvssMetricV2": [ - { - "source": "nvd@nist.gov", - "type": "Primary", - "cvssData": { - "version": "2.0", - "vectorString": "AV:N/AC:L/Au:N/C:N/I:N/A:P", - "confidentialityImpact": "NONE", - "integrityImpact": "NONE", - "availabilityImpact": "PARTIAL", - "baseScore": 5.0 - }, - "baseSeverity": "MEDIUM", - "exploitabilityScore": 10.0, - "impactScore": 2.9, - "acInsufInfo": false, - "obtainAllPrivilege": false, - "obtainUserPrivilege": false, - "obtainOtherPrivilege": false, - "userInteractionRequired": false - } - ] - } + "severity": [ + { + "type": "CVSS_V2", + "score": "AV:N/AC:L/Au:N/C:N/I:N/A:P" + } + ] }, { - "aliases": ["GHSA-jjjh-jjxp-wpff"], + "aliases": [ + "GHSA-jjjh-jjxp-wpff" + ], "cveId": "CVE-2022-42003", "created": "2024-01-15T21:37:47.413+00:00", "description": "In FasterXML jackson-databind 2.4.0-rc1 until 2.12.7.1 and in 2.13.x before 2.13.4.2 resource exhaustion can occur because of a lack of a check in primitive value deserializers to avoid deep wrapper array nesting, when the UNWRAP_SINGLE_VALUE_ARRAYS feature is enabled. This was patched in 2.12.7.1, 2.13.4.2, and 2.14.0.", @@ -447,7 +447,14 @@ "ranges": [ { "type": "ECOSYSTEM", - "events": [{ "introduced": "2.4.0-rc1" }, { "fixed": "2.12.7.1" }] + "events": [ + { + "introduced": "2.4.0-rc1" + }, + { + "fixed": "2.12.7.1" + } + ] } ], "versions": [ @@ -596,7 +603,14 @@ "ranges": [ { "type": "ECOSYSTEM", - "events": [{ "introduced": "2.13.0" }, { "fixed": "2.13.4.2" }] + "events": [ + { + "introduced": "2.13.0" + }, + { + "fixed": "2.13.4.2" + } + ] } ], "versions": [ @@ -611,33 +625,17 @@ ] } ], - "metrics": { - "cvssMetricV30": [ - { - "source": "nvd@nist.gov", - "type": "Primary", - "cvssData": { - "version": "3.0", - "vectorString": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H", - "attackVector": "NETWORK", - "attackComplexity": "LOW", - "privilegesRequired": "NONE", - "userInteraction": "NONE", - "scope": "UNCHANGED", - "confidentialityImpact": "NONE", - "integrityImpact": "NONE", - "availabilityImpact": "HIGH", - "baseScore": 7.5, - "baseSeverity": "HIGH" - }, - "exploitabilityScore": 3.9, - "impactScore": 3.6 - } - ] - } + "severity": [ + { + "type": "CVSS_V3", + "score": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H" + } + ] }, { - "aliases": ["GHSA-rgv9-q543-rqg4"], + "aliases": [ + "GHSA-rgv9-q543-rqg4" + ], "cveId": "CVE-2022-42004", "created": "2024-01-15T21:37:47.413+00:00", "summary": "Uncontrolled Resource Consumption in FasterXML jackson-databind", @@ -652,7 +650,14 @@ "ranges": [ { "type": "ECOSYSTEM", - "events": [{ "introduced": "0" }, { "fixed": "2.12.7.1" }] + "events": [ + { + "introduced": "0" + }, + { + "fixed": "2.12.7.1" + } + ] } ], "versions": [ @@ -829,7 +834,14 @@ "ranges": [ { "type": "ECOSYSTEM", - "events": [{ "introduced": "2.13.0" }, { "fixed": "2.13.4" }] + "events": [ + { + "introduced": "2.13.0" + }, + { + "fixed": "2.13.4" + } + ] } ], "versions": [ @@ -842,36 +854,20 @@ ] } ], - "metrics": { - "cvssMetricV31": [ - { - "source": "nvd@nist.gov", - "type": "Primary", - "cvssData": { - "version": "3.1", - "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H", - "attackVector": "NETWORK", - "attackComplexity": "LOW", - "privilegesRequired": "NONE", - "userInteraction": "NONE", - "scope": "UNCHANGED", - "confidentialityImpact": "NONE", - "integrityImpact": "NONE", - "availabilityImpact": "HIGH", - "baseScore": 7.5, - "baseSeverity": "HIGH" - }, - "exploitabilityScore": 3.9, - "impactScore": 3.6 - } - ] - } + "severity": [ + { + "type": "CVSS_V3", + "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H" + } + ] } ], "pkg:maven/jakarta.interceptor/jakarta.interceptor-api@1.2.5?type=jar": [], "pkg:maven/io.quarkus/quarkus-core@2.13.5.Final?type=jar": [ { - "aliases": ["GHSA-3fhx-3vvg-2j84"], + "aliases": [ + "GHSA-3fhx-3vvg-2j84" + ], "cveId": "CVE-2023-2974", "created": "2024-01-15T21:37:49.155+00:00", "description": "A vulnerability was found in quarkus-core. This vulnerability occurs because the TLS protocol configured with quarkus.http.ssl.protocols is not enforced, and the client can force the selection of the weaker supported TLS protocol.", @@ -885,7 +881,14 @@ "ranges": [ { "type": "ECOSYSTEM", - "events": [{ "introduced": "0" }, { "fixed": "2.16.8.Final" }] + "events": [ + { + "introduced": "0" + }, + { + "fixed": "2.16.8.Final" + } + ] } ], "versions": [ @@ -1104,50 +1107,12 @@ ] } ], - "metrics": { - "cvssMetricV31": [ - { - "source": "nvd@nist.gov", - "type": "Primary", - "cvssData": { - "version": "3.1", - "vectorString": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N", - "attackVector": "NETWORK", - "attackComplexity": "LOW", - "privilegesRequired": "LOW", - "userInteraction": "NONE", - "scope": "UNCHANGED", - "confidentialityImpact": "HIGH", - "integrityImpact": "HIGH", - "availabilityImpact": "NONE", - "baseScore": 8.1, - "baseSeverity": "HIGH" - }, - "exploitabilityScore": 2.8, - "impactScore": 5.2 - }, - { - "source": "secalert@redhat.com", - "type": "Secondary", - "cvssData": { - "version": "3.1", - "vectorString": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:N", - "attackVector": "NETWORK", - "attackComplexity": "LOW", - "privilegesRequired": "HIGH", - "userInteraction": "NONE", - "scope": "UNCHANGED", - "confidentialityImpact": "HIGH", - "integrityImpact": "HIGH", - "availabilityImpact": "NONE", - "baseScore": 6.5, - "baseSeverity": "MEDIUM" - }, - "exploitabilityScore": 1.2, - "impactScore": 5.2 - } - ] - } + "severity": [ + { + "type": "CVSS_V3", + "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N" + } + ] } ] -} +} \ No newline at end of file