diff --git a/src/main/java/io/github/guacsec/trustifyda/providers/CargoProvider.java b/src/main/java/io/github/guacsec/trustifyda/providers/CargoProvider.java index 2f8832bf..e82b1247 100644 --- a/src/main/java/io/github/guacsec/trustifyda/providers/CargoProvider.java +++ b/src/main/java/io/github/guacsec/trustifyda/providers/CargoProvider.java @@ -46,6 +46,7 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; +import java.util.TreeMap; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -285,8 +286,7 @@ void processWorkspaceDependencies( CargoPackage depPackage = findPackageByName(packageMap, depName); try { PackageURL depUrl = - new PackageURL( - Type.CARGO.getType(), null, depPackage.name(), depPackage.version(), null, null); + createCargoPurl(depPackage.name(), depPackage.version(), depPackage.isPathDependency()); sbom.addDependency(root, depUrl, null); } catch (Exception e) { log.warning("Failed to create PackageURL for workspace dependency: " + depName); @@ -332,8 +332,7 @@ private void processWorkspaceMember( try { PackageURL memberUrl = - new PackageURL( - Type.CARGO.getType(), null, memberPkg.name(), memberPkg.version(), null, null); + createCargoPurl(memberPkg.name(), memberPkg.version(), memberPkg.isPathDependency()); sbom.addDependency(workspaceRoot, memberUrl, null); if (debugLoggingIsNeeded()) { @@ -528,8 +527,7 @@ private void processDirectDependencies( try { PackageURL packageUrl = - new PackageURL( - Type.CARGO.getType(), null, childInfo.name(), childInfo.version(), null, null); + createCargoPurl(childInfo.name(), childInfo.version(), childInfo.isPathDependency()); sbom.addDependency(sourceUrl, packageUrl, null); if (debugLoggingIsNeeded()) { log.info( @@ -594,8 +592,7 @@ private void processDependencyNode( try { PackageURL childUrl = - new PackageURL( - Type.CARGO.getType(), null, childInfo.name(), childInfo.version(), null, null); + createCargoPurl(childInfo.name(), childInfo.version(), childInfo.isPathDependency()); String relationshipKey = parent.getCoordinates() + "->" + childUrl.getCoordinates(); @@ -641,7 +638,7 @@ private Map buildPackageMap(CargoMetadata metadata) { private DependencyInfo getPackageInfo(String packageId, Map packageMap) { CargoPackage pkg = packageMap.get(packageId); - return new DependencyInfo(pkg.name(), pkg.version()); + return new DependencyInfo(pkg.name(), pkg.version(), pkg.source()); } public CargoProvider(Path manifest) { @@ -821,4 +818,16 @@ private boolean lineContainsDependency(String trimmed, String depName) { } return false; } + + /** + * Creates a {@link PackageURL} for a Cargo package. Path dependencies ({@code source == null}) + * get a {@code repository_url=local} qualifier so the backend can distinguish them from registry + * packages and skip vulnerability checks. + */ + private static PackageURL createCargoPurl(String name, String version, boolean isPathDep) + throws Exception { + TreeMap qualifiers = + isPathDep ? new TreeMap<>(Map.of("repository_url", "local")) : null; + return new PackageURL(Type.CARGO.getType(), null, name, version, qualifiers, null); + } } diff --git a/src/main/java/io/github/guacsec/trustifyda/providers/rust/model/CargoPackage.java b/src/main/java/io/github/guacsec/trustifyda/providers/rust/model/CargoPackage.java index 5fc8a438..f47b76c7 100644 --- a/src/main/java/io/github/guacsec/trustifyda/providers/rust/model/CargoPackage.java +++ b/src/main/java/io/github/guacsec/trustifyda/providers/rust/model/CargoPackage.java @@ -24,5 +24,12 @@ public record CargoPackage( @JsonProperty("name") String name, @JsonProperty("version") String version, @JsonProperty("id") String id, + @JsonProperty("source") String source, @JsonProperty("manifest_path") String manifestPath, - @JsonProperty("dependencies") List dependencies) {} + @JsonProperty("dependencies") List dependencies) { + + /** Path dependencies have {@code source == null} in cargo metadata. */ + public boolean isPathDependency() { + return source == null; + } +} diff --git a/src/main/java/io/github/guacsec/trustifyda/providers/rust/model/DependencyInfo.java b/src/main/java/io/github/guacsec/trustifyda/providers/rust/model/DependencyInfo.java index 3111f2e2..02dd8510 100644 --- a/src/main/java/io/github/guacsec/trustifyda/providers/rust/model/DependencyInfo.java +++ b/src/main/java/io/github/guacsec/trustifyda/providers/rust/model/DependencyInfo.java @@ -16,4 +16,10 @@ */ package io.github.guacsec.trustifyda.providers.rust.model; -public record DependencyInfo(String name, String version) {} +public record DependencyInfo(String name, String version, String source) { + + /** Path dependencies have {@code source == null} in cargo metadata. */ + public boolean isPathDependency() { + return source == null; + } +}