Skip to content

Commit 3b8fa90

Browse files
ruromeroclaude
andcommitted
fix(cargo): resolve workspace-inherited license in Cargo.toml
When a Cargo.toml uses `license = { workspace = true }`, the tomlj library's getString() returns null because the value is an inline table, not a string. The license is silently dropped from the SBOM. Fix by using get() to retrieve the raw Object, checking instanceof String for direct values, and resolving from workspace.package.license when workspace inheritance is detected — following the existing version resolution pattern in parseCargoToml(). Fixes: TC-4528 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent b2119d6 commit 3b8fa90

4 files changed

Lines changed: 49 additions & 1 deletion

File tree

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

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ public final class CargoProvider extends Provider {
7171
private static final String PACKAGE_VERSION = "package.version";
7272
private static final String PACKAGE_VERSION_WORKSPACE = "package.version.workspace";
7373
private static final String WORKSPACE_PACKAGE_VERSION = "workspace.package.version";
74+
private static final String PACKAGE_LICENSE = "package.license";
75+
private static final String PACKAGE_LICENSE_WORKSPACE = "package.license.workspace";
76+
private static final String WORKSPACE_PACKAGE_LICENSE = "workspace.package.license";
7477
private static final long TIMEOUT =
7578
Long.parseLong(System.getProperty("trustify.cargo.timeout.seconds", "5"));
7679
private final String cargoExecutable;
@@ -671,7 +674,16 @@ private String readLicenseFromToml(TomlParseResult existingResult) {
671674
if (tomlResult.hasErrors()) {
672675
return null;
673676
}
674-
String license = tomlResult.getString("package.license");
677+
String license = null;
678+
Object licenseValue = tomlResult.get(PACKAGE_LICENSE);
679+
if (licenseValue instanceof String) {
680+
license = (String) licenseValue;
681+
} else if (licenseValue != null) {
682+
Boolean isWorkspaceLicense = tomlResult.getBoolean(PACKAGE_LICENSE_WORKSPACE);
683+
if (Boolean.TRUE.equals(isWorkspaceLicense)) {
684+
license = tomlResult.getString(WORKSPACE_PACKAGE_LICENSE);
685+
}
686+
}
675687
return LicenseUtils.getLicense(license, manifestPath);
676688
} catch (IOException e) {
677689
log.warning("Failed to read license from Cargo.toml: " + e.getMessage());

src/test/java/io/github/guacsec/trustifyda/providers/CargoProviderLicenseTest.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,20 @@ void readLicenseFromManifest_returns_null_when_no_license() {
5454
String license = provider.readLicenseFromManifest();
5555
assertThat(license).isNull();
5656
}
57+
58+
/** Verifies that workspace-inherited license resolves from [workspace.package]. */
59+
@Test
60+
void readLicenseFromManifest_returns_license_from_workspace_inheritance() {
61+
var provider = createProvider("cargo_workspace_license_inheritance");
62+
String license = provider.readLicenseFromManifest();
63+
assertThat(license).isEqualTo("Apache-2.0");
64+
}
65+
66+
/** Verifies graceful fallback when workspace inheritance has no license in workspace section. */
67+
@Test
68+
void readLicenseFromManifest_returns_null_when_workspace_inheritance_but_no_workspace_license() {
69+
var provider = createProvider("cargo_workspace_license_inheritance_no_license");
70+
String license = provider.readLicenseFromManifest();
71+
assertThat(license).isNull();
72+
}
5773
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[package]
2+
name = "test-project"
3+
version = "1.0.0"
4+
license = { workspace = true }
5+
6+
[dependencies]
7+
serde = "1.0"
8+
9+
[workspace.package]
10+
license = "Apache-2.0"
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[package]
2+
name = "test-project"
3+
version = "1.0.0"
4+
license = { workspace = true }
5+
6+
[dependencies]
7+
serde = "1.0"
8+
9+
[workspace.package]
10+
version = "1.0.0"

0 commit comments

Comments
 (0)