From 6b6642306235cdf627750fa03917bb6c7a422905 Mon Sep 17 00:00:00 2001 From: Ruben Romero Montes Date: Fri, 9 Aug 2024 12:12:54 +0200 Subject: [PATCH] fix: count unique transitive, direct and total independently Signed-off-by: Ruben Romero Montes --- .../providers/ProviderResponseHandler.java | 26 ++++++++-- .../ProviderResponseHandlerTest.java | 52 +++++++++++++++++++ 2 files changed, 74 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/redhat/exhort/integration/providers/ProviderResponseHandler.java b/src/main/java/com/redhat/exhort/integration/providers/ProviderResponseHandler.java index 5426304a..99392314 100644 --- a/src/main/java/com/redhat/exhort/integration/providers/ProviderResponseHandler.java +++ b/src/main/java/com/redhat/exhort/integration/providers/ProviderResponseHandler.java @@ -26,6 +26,7 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; @@ -53,6 +54,7 @@ import com.redhat.exhort.model.CvssScoreComparable.DependencyScoreComparator; import com.redhat.exhort.model.CvssScoreComparable.TransitiveScoreComparator; import com.redhat.exhort.model.DependencyTree; +import com.redhat.exhort.model.DirectDependency; import com.redhat.exhort.model.ProviderResponse; import com.redhat.exhort.model.trustedcontent.IndexedRecommendation; import com.redhat.exhort.model.trustedcontent.TrustedContentResponse; @@ -425,9 +427,21 @@ private SourceSummary buildSummary( var counter = new VulnerabilityCounter(); var directRefs = tree.dependencies().keySet().stream().map(PackageRef::ref).collect(Collectors.toSet()); + var transitiveRefs = + tree.dependencies().values().stream() + .map(DirectDependency::transitive) + .flatMap(Set::stream) + .map(PackageRef::ref) + .toList(); issuesData .entrySet() - .forEach(e -> incrementCounter(e.getValue(), counter, directRefs.contains(e.getKey()))); + .forEach( + e -> + incrementCounter( + e.getValue(), + counter, + directRefs.contains(e.getKey()), + transitiveRefs.contains(e.getKey()))); Long recommendationsCount = sourceReport.stream().filter(s -> s.getRecommendation() != null).count(); counter.recommendations.set(recommendationsCount.intValue()); @@ -436,7 +450,7 @@ private SourceSummary buildSummary( } private void incrementCounter( - List issues, VulnerabilityCounter counter, boolean isDirect) { + List issues, VulnerabilityCounter counter, boolean isDirect, boolean isTransitive) { if (!issues.isEmpty()) { counter.dependencies.incrementAndGet(); } @@ -453,6 +467,9 @@ private void incrementCounter( if (isDirect) { counter.direct.addAndGet(vulnerabilities); } + if (isTransitive) { + counter.transitive.addAndGet(vulnerabilities); + } if (i.getRemediation() != null && i.getRemediation().getTrustedContent() != null && i.getRemediation().getTrustedContent().getRef() != null) { @@ -475,6 +492,7 @@ private int countVulnerabilities(Issue i) { private static final record VulnerabilityCounter( AtomicInteger total, + AtomicInteger transitive, AtomicInteger critical, AtomicInteger high, AtomicInteger medium, @@ -496,6 +514,7 @@ private static final record VulnerabilityCounter( new AtomicInteger(), new AtomicInteger(), new AtomicInteger(), + new AtomicInteger(), new AtomicInteger()); } @@ -507,10 +526,9 @@ SourceSummary getSummary() { .medium(medium.get()) .low(low.get()) .direct(direct.get()) - .transitive(total.get() - direct.get()) + .transitive(transitive.get()) .dependencies(dependencies.get()) .remediations(remediations.get()) - // Will be calculated later when TC recommendations will be added. .recommendations(recommendations.get()) .unscanned(unscanned.get()); } diff --git a/src/test/java/com/redhat/exhort/integration/providers/ProviderResponseHandlerTest.java b/src/test/java/com/redhat/exhort/integration/providers/ProviderResponseHandlerTest.java index d98eb5bd..8321ff54 100644 --- a/src/test/java/com/redhat/exhort/integration/providers/ProviderResponseHandlerTest.java +++ b/src/test/java/com/redhat/exhort/integration/providers/ProviderResponseHandlerTest.java @@ -133,6 +133,19 @@ private static Stream getSummaryValues() { .transitive(1) .medium(2) .dependencies(2) + .unscanned(0)), + Arguments.of( + Map.of( + "pkg:npm/aa@1", List.of(buildIssue(1, 5f)), + "pkg:npm/aaa@1", List.of(buildIssue(2, 5f))), + null, + buildTreeWithSameTransitiveDirect(), + new SourceSummary() + .total(2) + .direct(2) + .transitive(1) + .medium(2) + .dependencies(2) .unscanned(0))); } @@ -622,6 +635,45 @@ private static DependencyTree buildTreeWithDuplicates() { return DependencyTree.builder().dependencies(direct).build(); } + private static DependencyTree buildTreeWithSameTransitiveDirect() { + Map direct = + Map.of( + PackageRef.builder() + .name("aa") + .version("1") + .pkgManager(Constants.NPM_PURL_TYPE) + .build(), + DirectDependency.builder() + .ref( + PackageRef.builder() + .name("aa") + .version("1") + .pkgManager(Constants.NPM_PURL_TYPE) + .build()) + .transitive( + Set.of( + PackageRef.builder() + .name("aaa") + .version("1") + .pkgManager(Constants.NPM_PURL_TYPE) + .build())) + .build(), + PackageRef.builder() + .name("aaa") + .version("1") + .pkgManager(Constants.NPM_PURL_TYPE) + .build(), + DirectDependency.builder() + .ref( + PackageRef.builder() + .name("aaa") + .version("1") + .pkgManager(Constants.NPM_PURL_TYPE) + .build()) + .build()); + return DependencyTree.builder().dependencies(direct).build(); + } + private static Issue buildIssue(int id, Float score) { return new Issue() .id(String.format("ISSUE-00%d", id))