From 2cc7a4667909d751aef7eb51a9272c6dfdd6edcd Mon Sep 17 00:00:00 2001 From: vithikashukla Date: Tue, 4 Jun 2024 14:06:37 +0100 Subject: [PATCH] add cvss vector to vulnerability Signed-off-by: vithikashukla --- .../persistence/jdbi/NotificationSubjectDao.java | 8 ++++++++ .../jdbi/mapping/NotificationVulnerabilityRowMapper.java | 2 ++ .../dependencytrack/notification/v1/notification.proto | 2 ++ .../processor/VulnerabilityScanResultProcessorTest.java | 5 +++++ 4 files changed, 17 insertions(+) diff --git a/src/main/java/org/dependencytrack/persistence/jdbi/NotificationSubjectDao.java b/src/main/java/org/dependencytrack/persistence/jdbi/NotificationSubjectDao.java index 70020af28..e8f64de51 100644 --- a/src/main/java/org/dependencytrack/persistence/jdbi/NotificationSubjectDao.java +++ b/src/main/java/org/dependencytrack/persistence/jdbi/NotificationSubjectDao.java @@ -104,6 +104,14 @@ public interface NotificationSubjectDao extends SqlObject { WHEN "A"."SEVERITY" IS NOT NULL THEN "A"."CVSSV3SCORE" ELSE "V"."CVSSV3BASESCORE" END AS "vulnCvssV3BaseScore", + CASE + WHEN "A"."CVSSV2VECTOR" IS NOT NULL THEN "A"."CVSSV2VECTOR" + ELSE "V"."CVSSV2VECTOR" + END AS "vulnCvssV2Vector", + CASE + WHEN "A"."CVSSV3VECTOR" IS NOT NULL THEN "A"."CVSSV3VECTOR" + ELSE "V"."CVSSV3VECTOR" + END AS "vulnCvssV3Vector", -- TODO: Analysis only has a single score, but OWASP RR defines multiple. -- How to handle this? CASE diff --git a/src/main/java/org/dependencytrack/persistence/jdbi/mapping/NotificationVulnerabilityRowMapper.java b/src/main/java/org/dependencytrack/persistence/jdbi/mapping/NotificationVulnerabilityRowMapper.java index 63f613189..de03f619a 100644 --- a/src/main/java/org/dependencytrack/persistence/jdbi/mapping/NotificationVulnerabilityRowMapper.java +++ b/src/main/java/org/dependencytrack/persistence/jdbi/mapping/NotificationVulnerabilityRowMapper.java @@ -52,6 +52,8 @@ public Vulnerability map(final ResultSet rs, final StatementContext ctx) throws maybeSet(rs, "vulnRecommendation", ResultSet::getString, builder::setRecommendation); maybeSet(rs, "vulnCvssV2BaseScore", RowMapperUtil::nullableDouble, builder::setCvssV2); maybeSet(rs, "vulnCvssV3BaseScore", RowMapperUtil::nullableDouble, builder::setCvssV3); + maybeSet(rs, "vulnCvssV2Vector", ResultSet::getString, builder::setCvssV2Vector); + maybeSet(rs, "vulnCvssV3Vector", ResultSet::getString, builder::setCvssV3Vector); maybeSet(rs, "vulnOwaspRrBusinessImpactScore", RowMapperUtil::nullableDouble, builder::setOwaspRrBusinessImpact); maybeSet(rs, "vulnOwaspRrLikelihoodScore", RowMapperUtil::nullableDouble, builder::setOwaspRrLikelihood); maybeSet(rs, "vulnOwaspRrTechnicalImpactScore", RowMapperUtil::nullableDouble, builder::setOwaspRrTechnicalImpact); diff --git a/src/main/proto/org/dependencytrack/notification/v1/notification.proto b/src/main/proto/org/dependencytrack/notification/v1/notification.proto index a03e2881a..a42c2285c 100644 --- a/src/main/proto/org/dependencytrack/notification/v1/notification.proto +++ b/src/main/proto/org/dependencytrack/notification/v1/notification.proto @@ -189,6 +189,8 @@ message Vulnerability { optional double owasp_rr_business_impact = 13 [json_name = "owaspRRBusinessImpact"]; optional string severity = 14; repeated Cwe cwes = 15; + optional string cvss_v2_vector = 16; + optional string cvss_v3_vector = 17; message Alias { string id = 1 [json_name = "vulnId"]; diff --git a/src/test/java/org/dependencytrack/event/kafka/processor/VulnerabilityScanResultProcessorTest.java b/src/test/java/org/dependencytrack/event/kafka/processor/VulnerabilityScanResultProcessorTest.java index 595207f8e..2fa09b32e 100644 --- a/src/test/java/org/dependencytrack/event/kafka/processor/VulnerabilityScanResultProcessorTest.java +++ b/src/test/java/org/dependencytrack/event/kafka/processor/VulnerabilityScanResultProcessorTest.java @@ -246,10 +246,13 @@ public void processSuccessfulScanResult() { final var vulnA = new Vulnerability(); vulnA.setVulnId("INT-001"); vulnA.setSource(Vulnerability.Source.INTERNAL); + vulnA.setCvssV2Vector("(AV:N/AC:M/Au:S/C:P/I:P/A:P)"); qm.persist(vulnA); final var vulnB = new Vulnerability(); vulnB.setVulnId("SONATYPE-002"); vulnB.setSource(Vulnerability.Source.OSSINDEX); + vulnB.setCvssV3Vector("CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H"); + qm.persist(vulnB); final var vulnC = new Vulnerability(); vulnC.setVulnId("INT-002"); vulnC.setSource(Vulnerability.Source.INTERNAL); @@ -326,6 +329,7 @@ record -> { assertThat(notification.getGroup()).isEqualTo(GROUP_NEW_VULNERABILITY); assertThat(notification.getSubject().is(NewVulnerabilitySubject.class)).isTrue(); final var subject = notification.getSubject().unpack(NewVulnerabilitySubject.class); + assertThat(subject.getVulnerability().getCvssV2Vector()).isEqualTo("(AV:N/AC:M/Au:S/C:P/I:P/A:P)"); assertThat(subject.getVulnerabilityAnalysisLevel()).isEqualTo("BOM_UPLOAD_ANALYSIS"); }, record -> { @@ -336,6 +340,7 @@ record -> { assertThat(notification.getGroup()).isEqualTo(GROUP_NEW_VULNERABILITY); assertThat(notification.getSubject().is(NewVulnerabilitySubject.class)).isTrue(); final var subject = notification.getSubject().unpack(NewVulnerabilitySubject.class); + assertThat(subject.getVulnerability().getCvssV3Vector()).isEqualTo("CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H"); assertThat(subject.getVulnerabilityAnalysisLevel()).isEqualTo("BOM_UPLOAD_ANALYSIS"); } // INT-002 is discarded because it is internal but doesn't exist in the database.