Skip to content

Commit 26c2423

Browse files
authored
fix: java stack analysis doesn't ignore deps inherited version (#234)
fix: java stack analysis doesn'tt ignore deps inherited version @ruromero could you review this? This follows the same approach implemented in guacsec/trustify-da-javascript-client#219 Thanks. fixes: #233 ## Checklist - [x] I have followed this repository's contributing guidelines. - [x] I will adhere to the project's code of conduct.
1 parent 2d2b734 commit 26c2423

3 files changed

Lines changed: 61 additions & 11 deletions

File tree

src/main/java/io/github/guacsec/trustifyda/providers/JavaMavenProvider.java

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -75,24 +75,32 @@ public Content provideStack() throws IOException {
7575
// create a temp file for storing the dependency tree in
7676
var tmpFile = Files.createTempFile("TRUSTIFY_DA_dot_graph_", null);
7777
// the tree command will build the project and create the dependency tree in the temp file
78-
var mvnTreeCmd =
79-
buildMvnCommandArgs(
80-
"org.apache.maven.plugins:maven-dependency-plugin:3.6.0:tree",
81-
"-Dverbose",
82-
"-DoutputType=text",
83-
String.format("-DoutputFile=%s", tmpFile.toString()),
84-
"-f",
85-
manifest.toString(),
86-
"--batch-mode",
87-
"-q");
78+
var mvnTreeCmdArgs =
79+
new ArrayList<>(
80+
List.of(
81+
"org.apache.maven.plugins:maven-dependency-plugin:3.6.0:tree",
82+
"-Dscope=compile",
83+
"-Dverbose",
84+
"-DoutputType=text",
85+
String.format("-DoutputFile=%s", tmpFile.toString()),
86+
"-f",
87+
manifest.toString(),
88+
"--batch-mode",
89+
"-q"));
8890
// if we have dependencies marked as ignored, exclude them from the tree command
8991
var ignored =
9092
getDependencies(manifest).stream()
9193
.filter(d -> d.ignored)
92-
.map(DependencyAggregator::toPurl)
94+
.map(DependencyAggregator::toPurlWithoutVersion)
9395
.map(PackageURL::getCoordinates)
9496
.collect(Collectors.toList());
97+
98+
if (!ignored.isEmpty()) {
99+
mvnTreeCmdArgs.add("-Dexcludes=" + String.join(",", ignored));
100+
}
101+
95102
// execute the tree command
103+
var mvnTreeCmd = buildMvnCommandArgs(mvnTreeCmdArgs.toArray(String[]::new));
96104
Operations.runProcess(manifest.getParent(), mvnTreeCmd.toArray(String[]::new), mvnEnvs);
97105
if (debugLoggingIsNeeded()) {
98106
String stackAnalysisDependencyTree = Files.readString(tmpFile);
@@ -110,6 +118,7 @@ public Content provideStack() throws IOException {
110118

111119
private Sbom buildSbomFromTextFormat(Path textFormatFile) throws IOException {
112120
var sbom = SbomFactory.newInstance(Sbom.BelongingCondition.PURL, "sensitive");
121+
sbom.setCoordinateBasedMatching();
113122
List<String> lines = Files.readAllLines(textFormatFile);
114123
var root = lines.get(0);
115124
var rootPurl = parseDep(root);
@@ -408,6 +417,15 @@ public PackageURL toPurl() {
408417
}
409418
}
410419

420+
/** Creates a PackageURL without version for coordinate-based matching. */
421+
public PackageURL toPurlWithoutVersion() {
422+
try {
423+
return new PackageURL(Type.MAVEN.getType(), groupId, artifactId, null, null, null);
424+
} catch (MalformedPackageURLException e) {
425+
throw new IllegalArgumentException("Unable to parse PackageURL", e);
426+
}
427+
}
428+
411429
@Override
412430
public boolean equals(Object o) {
413431
if (this == o) return true;

src/main/java/io/github/guacsec/trustifyda/sbom/CycloneDXSbom.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,31 @@ private BiPredicate<Collection<?>, Component> getBelongingConditionByPurl() {
9595
collection.contains(componentToPurl(component).getCoordinates());
9696
}
9797

98+
/**
99+
* Creates a coordinate-based belonging condition that matches by groupId:artifactId only,
100+
* ignoring version. Used for handling dependencies with unresolved version properties.
101+
*/
102+
private BiPredicate<Collection<?>, Component> getBelongingConditionByCoordinatesOnly() {
103+
return (collection, component) -> {
104+
PackageURL componentPurl = componentToPurl(component);
105+
String componentCoords = componentPurl.getNamespace() + ":" + componentPurl.getName();
106+
107+
return collection.stream()
108+
.filter(String.class::isInstance)
109+
.map(String.class::cast)
110+
.anyMatch(
111+
ignoredPurlCoords -> {
112+
try {
113+
PackageURL ignoredPurl = new PackageURL(ignoredPurlCoords);
114+
String ignoredCoords = ignoredPurl.getNamespace() + ":" + ignoredPurl.getName();
115+
return componentCoords.equals(ignoredCoords);
116+
} catch (MalformedPackageURLException e) {
117+
return false;
118+
}
119+
});
120+
};
121+
}
122+
98123
public Sbom addRoot(PackageURL rootRef) {
99124
this.root = rootRef;
100125
Component rootComponent = newRootComponent(rootRef);
@@ -280,6 +305,11 @@ public void setBelongingCriteriaBinaryAlgorithm(BelongingCondition belongingCond
280305
}
281306
}
282307

308+
@Override
309+
public void setCoordinateBasedMatching() {
310+
belongingCriteriaBinaryAlgorithm = getBelongingConditionByCoordinatesOnly();
311+
}
312+
283313
@Override
284314
public boolean checkIfPackageInsideDependsOnList(PackageURL component, String name) {
285315
boolean result = false;

src/main/java/io/github/guacsec/trustifyda/sbom/Sbom.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ public interface Sbom {
3333

3434
public void setBelongingCriteriaBinaryAlgorithm(BelongingCondition belongingCondition);
3535

36+
public void setCoordinateBasedMatching();
37+
3638
public boolean checkIfPackageInsideDependsOnList(PackageURL component, String name);
3739

3840
void removeRootComponent();

0 commit comments

Comments
 (0)