This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new 68414dacd0a7 CAMEL-23912: CVE Audit tab shows which dependency pulls 
in vulnerable JAR
68414dacd0a7 is described below

commit 68414dacd0a7cf3650cb6889146e08a36c82af80
Author: Claus Ibsen <[email protected]>
AuthorDate: Mon Jul 6 12:49:03 2026 +0200

    CAMEL-23912: CVE Audit tab shows which dependency pulls in vulnerable JAR
    
    For transitive dependencies with CVEs, show "(via parent-artifact)" in
    both the table ARTIFACT column and the detail view's affected artifacts
    list so users know which direct dependency to upgrade.
    
    Co-Authored-By: Claude <[email protected]>
    Signed-off-by: Claus Ibsen <[email protected]>
    Signed-off-by: Claus Ibsen <[email protected]>
---
 .../dsl/jbang/core/commands/tui/CveAuditTab.java   | 40 ++++++++++++++++++----
 .../core/commands/tui/CveAuditTabRenderTest.java   |  8 ++---
 2 files changed, 38 insertions(+), 10 deletions(-)

diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CveAuditTab.java
 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CveAuditTab.java
index 278b6f3fe355..09dc5bb02af1 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CveAuditTab.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CveAuditTab.java
@@ -207,8 +207,15 @@ class CveAuditTab extends AbstractTableTab {
         List<Row> rows = new ArrayList<>();
         for (VulnGroup group : visible) {
             String firstArtifact = group.affectedGavs.isEmpty() ? "" : 
group.affectedGavs.get(0);
+            String firstParent = group.affectedGavs.isEmpty() ? null : 
group.gavParents.get(firstArtifact);
             int artCount = group.affectedGavs.size();
-            String artDisplay = artCount > 1 ? firstArtifact + " (+" + 
(artCount - 1) + ")" : firstArtifact;
+            String artDisplay = firstArtifact;
+            if (firstParent != null) {
+                artDisplay += " (via " + firstParent + ")";
+            }
+            if (artCount > 1) {
+                artDisplay += " (+" + (artCount - 1) + ")";
+            }
 
             rows.add(Row.from(
                     Cell.from(Span.styled(group.severity != null ? 
group.severity : "", severityStyle(group.severity))),
@@ -278,7 +285,12 @@ class CveAuditTab extends AbstractTableTab {
         }
         md.append("**Affected artifacts:**\n");
         for (String gav : group.affectedGavs) {
-            md.append("- `").append(gav).append("`\n");
+            String parent = group.gavParents.get(gav);
+            md.append("- `").append(gav).append("`");
+            if (parent != null) {
+                md.append(" *(via ").append(parent).append(")*");
+            }
+            md.append("\n");
         }
         if (!group.fixedVersions.isEmpty()) {
             md.append("\n**Fixed in:** ").append(String.join(", ", 
group.fixedVersions)).append("\n");
@@ -390,7 +402,14 @@ class CveAuditTab extends AbstractTableTab {
 
                 Map<String, List<OsvClient.Vulnerability>> vulnMap = 
osvClient.queryBatch(allDeps);
 
-                List<VulnGroup> groups = buildVulnGroups(vulnMap);
+                Map<String, String> gavToParent = new HashMap<>();
+                for (DependencyLoader.DepEntry dep : allDeps) {
+                    if (dep.transitive() && dep.parent() != null) {
+                        gavToParent.put(dep.display(), 
DependencyLoader.shortArtifact(dep.parent()));
+                    }
+                }
+
+                List<VulnGroup> groups = buildVulnGroups(vulnMap, gavToParent);
                 groups.sort(Comparator
                         .comparingInt((VulnGroup g) -> 
severityIndex(g.severity))
                         .thenComparing(g -> g.canonicalId));
@@ -436,7 +455,8 @@ class CveAuditTab extends AbstractTableTab {
         return result;
     }
 
-    static List<VulnGroup> buildVulnGroups(Map<String, 
List<OsvClient.Vulnerability>> vulnMap) {
+    static List<VulnGroup> buildVulnGroups(
+            Map<String, List<OsvClient.Vulnerability>> vulnMap, Map<String, 
String> gavToParent) {
         Map<String, String> aliasToCanonical = new HashMap<>();
         Map<String, VulnGroup> groups = new LinkedHashMap<>();
 
@@ -449,7 +469,8 @@ class CveAuditTab extends AbstractTableTab {
                 if (group == null) {
                     group = new VulnGroup(
                             canonicalId, normalizeSeverity(vuln.severity()), 
vuln.cvssVector(), vuln.summary(),
-                            vuln.details(), vuln.published(), new 
ArrayList<>(), new ArrayList<>(), new ArrayList<>());
+                            vuln.details(), vuln.published(), new 
ArrayList<>(), new HashMap<>(),
+                            new ArrayList<>(), new ArrayList<>());
                     groups.put(canonicalId, group);
                     aliasToCanonical.put(vuln.id(), canonicalId);
                     for (String alias : vuln.aliases()) {
@@ -459,6 +480,10 @@ class CveAuditTab extends AbstractTableTab {
 
                 if (!group.affectedGavs.contains(gav)) {
                     group.affectedGavs.add(gav);
+                    String parent = gavToParent.get(gav);
+                    if (parent != null) {
+                        group.gavParents.put(gav, parent);
+                    }
                 }
                 for (String alias : vuln.aliases()) {
                     if (!alias.equals(canonicalId) && 
!group.aliases.contains(alias)) {
@@ -623,11 +648,13 @@ class CveAuditTab extends AbstractTableTab {
         final String details;
         final String published;
         final List<String> affectedGavs;
+        final Map<String, String> gavParents;
         final List<String> aliases;
         final List<String> fixedVersions;
 
         VulnGroup(String canonicalId, String severity, String cvssVector, 
String summary, String details,
-                  String published, List<String> affectedGavs, List<String> 
aliases, List<String> fixedVersions) {
+                  String published, List<String> affectedGavs, Map<String, 
String> gavParents,
+                  List<String> aliases, List<String> fixedVersions) {
             this.canonicalId = canonicalId;
             this.severity = severity;
             this.cvssVector = cvssVector;
@@ -635,6 +662,7 @@ class CveAuditTab extends AbstractTableTab {
             this.details = details;
             this.published = published;
             this.affectedGavs = affectedGavs;
+            this.gavParents = gavParents;
             this.aliases = aliases;
             this.fixedVersions = fixedVersions;
         }
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/test/java/org/apache/camel/dsl/jbang/core/commands/tui/CveAuditTabRenderTest.java
 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/test/java/org/apache/camel/dsl/jbang/core/commands/tui/CveAuditTabRenderTest.java
index 77983cb3c6a4..71c23e38e7a2 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/test/java/org/apache/camel/dsl/jbang/core/commands/tui/CveAuditTabRenderTest.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/test/java/org/apache/camel/dsl/jbang/core/commands/tui/CveAuditTabRenderTest.java
@@ -86,7 +86,7 @@ class CveAuditTabRenderTest {
                         "CVE-2024-1234", "Test vuln", null, "HIGH", null, 
"2024-01-01",
                         List.of("GHSA-xxxx"), List.of("1.1"))));
 
-        List<CveAuditTab.VulnGroup> groups = 
CveAuditTab.buildVulnGroups(vulnMap);
+        List<CveAuditTab.VulnGroup> groups = 
CveAuditTab.buildVulnGroups(vulnMap, Map.of());
 
         assertEquals(1, groups.size(), "Should deduplicate CVE-2024-1234 and 
GHSA-xxxx into one group");
         assertEquals("CVE-2024-1234", groups.get(0).canonicalId, "Should 
prefer CVE- prefix as canonical ID");
@@ -102,7 +102,7 @@ class CveAuditTabRenderTest {
                 new OsvClient.Vulnerability(
                         "CVE-2024-2222", "Vuln B", null, "MEDIUM", null, 
"2024-02-01", List.of(), List.of())));
 
-        List<CveAuditTab.VulnGroup> groups = 
CveAuditTab.buildVulnGroups(vulnMap);
+        List<CveAuditTab.VulnGroup> groups = 
CveAuditTab.buildVulnGroups(vulnMap, Map.of());
 
         assertEquals(2, groups.size(), "Should create separate groups for 
distinct CVEs");
     }
@@ -119,7 +119,7 @@ class CveAuditTabRenderTest {
                         "CVE-2024-9999", "Critical vuln", null, "CRITICAL", 
null, "2024-01-01",
                         List.of(), List.of())));
 
-        List<CveAuditTab.VulnGroup> groups = 
CveAuditTab.buildVulnGroups(vulnMap);
+        List<CveAuditTab.VulnGroup> groups = 
CveAuditTab.buildVulnGroups(vulnMap, Map.of());
         assertFalse(groups.isEmpty());
         assertEquals("CRITICAL", groups.get(0).severity);
 
@@ -162,7 +162,7 @@ class CveAuditTabRenderTest {
                         "CVE-2024-6666", "Other vuln", null, "LOW", null, 
"2024-01-01",
                         List.of(), List.of())));
 
-        List<CveAuditTab.VulnGroup> groups = 
CveAuditTab.buildVulnGroups(vulnMap);
+        List<CveAuditTab.VulnGroup> groups = 
CveAuditTab.buildVulnGroups(vulnMap, Map.of());
         assertEquals(2, groups.size());
     }
 }

Reply via email to