Skip to content

Commit 5b4d9cb

Browse files
committed
Handle UNLICENSED NuGet license expression
Signed-off-by: Lakshya Jain <lakshyajain1995@gmail.com>
1 parent 0ae5d6a commit 5b4d9cb

2 files changed

Lines changed: 47 additions & 2 deletions

File tree

CycloneDX.Tests/NugetV3ServiceTests.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,38 @@ public async Task GetComponent_SingleLicenseExpression_ReturnsComponent()
482482
Assert.Equal("Apache-2.0", component.Licenses.First().License.Id);
483483
}
484484

485+
[Fact]
486+
public async Task GetComponent_UnlicensedLicenseExpression_MapsToLicenseName()
487+
{
488+
var nuspecFileContents = @"<?xml version=""1.0"" encoding=""utf-8""?>
489+
<package xmlns=""http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd"">
490+
<metadata>
491+
<id>testpackage</id>
492+
<license type=""expression"">UNLICENSED</license>
493+
</metadata>
494+
</package>";
495+
var mockFileSystem = new MockFileSystem(new Dictionary<string, MockFileData>
496+
{
497+
{ XFS.Path(@"c:\nugetcache\testpackage\1.0.0\testpackage.nuspec"), new MockFileData(nuspecFileContents) },
498+
});
499+
500+
var mockGitHubService = new Mock<IGithubService>();
501+
502+
var nugetService = new NugetV3Service(null,
503+
mockFileSystem,
504+
new List<string> { XFS.Path(@"c:\nugetcache") },
505+
mockGitHubService.Object,
506+
new NullLogger(), false);
507+
508+
var component = await nugetService.GetComponentAsync("testpackage", "1.0.0", Component.ComponentScope.Required).ConfigureAwait(true);
509+
510+
Assert.Single(component.Licenses);
511+
Assert.Equal("UNLICENSED", component.Licenses.First().License.Name);
512+
Assert.True(string.IsNullOrEmpty(component.Licenses.First().License.Id));
513+
}
514+
515+
516+
485517
[Fact]
486518
public async Task GetComponent_MultiLicenseExpression_ReturnsComponent()
487519
{

CycloneDX/Services/NugetV3Service.cs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -262,12 +262,25 @@ public async Task<Component> GetComponentAsync(string name, string version, Comp
262262
{
263263
Action<NuGetLicense> licenseProcessor = delegate (NuGetLicense nugetLicense)
264264
{
265+
var identifier = nugetLicense?.Identifier?.Trim();
265266
var license = new License();
266-
license.Id = nugetLicense.Identifier;
267-
license.Name = license.Id == null ? nugetLicense.Identifier : null;
267+
268+
// UNLICENSED is not a valid SPDX license id, so emit as name instead.
269+
// (Avoids generating invalid CycloneDX output like <id>UNLICENSED</id>.)
270+
if (!string.IsNullOrEmpty(identifier) &&
271+
string.Equals(identifier, "UNLICENSED", StringComparison.OrdinalIgnoreCase))
272+
{
273+
license.Name = "UNLICENSED";
274+
}
275+
else
276+
{
277+
license.Id = identifier;
278+
}
279+
268280
component.Licenses ??= new List<LicenseChoice>();
269281
component.Licenses.Add(new LicenseChoice { License = license });
270282
};
283+
271284
licenseMetadata.LicenseExpression.OnEachLeafNode(licenseProcessor, null);
272285
}
273286
else if (_githubService == null)

0 commit comments

Comments
 (0)