diff --git a/src/Microsoft.Sbom.Adapters/Adapters/ComponentDetection/CargoComponentExtensions.cs b/src/Microsoft.Sbom.Adapters/Adapters/ComponentDetection/CargoComponentExtensions.cs index d6396c08b..ea115d420 100644 --- a/src/Microsoft.Sbom.Adapters/Adapters/ComponentDetection/CargoComponentExtensions.cs +++ b/src/Microsoft.Sbom.Adapters/Adapters/ComponentDetection/CargoComponentExtensions.cs @@ -3,7 +3,6 @@ namespace Microsoft.Sbom.Adapters.ComponentDetection; -using System.Linq; using Microsoft.ComponentDetection.Contracts.TypedComponent; using Microsoft.Sbom.Contracts; @@ -30,6 +29,6 @@ internal static class CargoComponentExtensions }, FilesAnalyzed = false, Type = "cargo", - DependOn = component.AncestralReferrers?.Select(r => r.Id).ToList(), + DependOn = null }; } diff --git a/src/Microsoft.Sbom.Adapters/Adapters/ComponentDetection/MavenComponentExtensions.cs b/src/Microsoft.Sbom.Adapters/Adapters/ComponentDetection/MavenComponentExtensions.cs index 24ba532d3..42ca7944f 100644 --- a/src/Microsoft.Sbom.Adapters/Adapters/ComponentDetection/MavenComponentExtensions.cs +++ b/src/Microsoft.Sbom.Adapters/Adapters/ComponentDetection/MavenComponentExtensions.cs @@ -3,7 +3,6 @@ namespace Microsoft.Sbom.Adapters.ComponentDetection; -using System.Linq; using Microsoft.ComponentDetection.Contracts.TypedComponent; using Microsoft.Sbom.Contracts; @@ -31,6 +30,6 @@ internal static class MavenComponentExtensions Declared = component.LicenseDeclared, }, Type = "maven", - DependOn = component.AncestralReferrers?.Select(r => r.Id).ToList(), + DependOn = null }; } diff --git a/src/Microsoft.Sbom.Adapters/Adapters/ComponentDetection/NpmComponentExtensions.cs b/src/Microsoft.Sbom.Adapters/Adapters/ComponentDetection/NpmComponentExtensions.cs index 8a1398613..f1c769db6 100644 --- a/src/Microsoft.Sbom.Adapters/Adapters/ComponentDetection/NpmComponentExtensions.cs +++ b/src/Microsoft.Sbom.Adapters/Adapters/ComponentDetection/NpmComponentExtensions.cs @@ -4,7 +4,6 @@ namespace Microsoft.Sbom.Adapters.ComponentDetection; using System; -using System.Linq; using Microsoft.ComponentDetection.Contracts.Internal; using Microsoft.ComponentDetection.Contracts.TypedComponent; using Microsoft.Sbom.Contracts; @@ -40,7 +39,7 @@ internal static class NpmComponentExtensions }, FilesAnalyzed = false, Type = "npm", - DependOn = component.AncestralReferrers?.Select(r => r.Id).ToList(), + DependOn = null }; /// diff --git a/src/Microsoft.Sbom.Adapters/Adapters/ComponentDetection/NuGetComponentExtensions.cs b/src/Microsoft.Sbom.Adapters/Adapters/ComponentDetection/NuGetComponentExtensions.cs index e3a9266b7..f5520d30c 100644 --- a/src/Microsoft.Sbom.Adapters/Adapters/ComponentDetection/NuGetComponentExtensions.cs +++ b/src/Microsoft.Sbom.Adapters/Adapters/ComponentDetection/NuGetComponentExtensions.cs @@ -32,6 +32,6 @@ internal static class NuGetComponentExtensions }, FilesAnalyzed = false, Type = "nuget", - DependOn = component.AncestralReferrers?.Select(r => r.Id).ToList(), + DependOn = null }; } diff --git a/src/Microsoft.Sbom.Adapters/Adapters/ComponentDetection/PipComponentExtensions.cs b/src/Microsoft.Sbom.Adapters/Adapters/ComponentDetection/PipComponentExtensions.cs index d30cb0de6..0d4f6795f 100644 --- a/src/Microsoft.Sbom.Adapters/Adapters/ComponentDetection/PipComponentExtensions.cs +++ b/src/Microsoft.Sbom.Adapters/Adapters/ComponentDetection/PipComponentExtensions.cs @@ -3,7 +3,6 @@ namespace Microsoft.Sbom.Adapters.ComponentDetection; -using System.Linq; using Microsoft.ComponentDetection.Contracts.TypedComponent; using Microsoft.Sbom.Contracts; @@ -30,6 +29,6 @@ internal static class PipComponentExtensions }, FilesAnalyzed = false, Type = "python", - DependOn = component.AncestralReferrers?.Select(r => r.Id).ToList(), + DependOn = null }; } diff --git a/src/Microsoft.Sbom.Adapters/Adapters/ComponentDetection/PodComponentExtensions.cs b/src/Microsoft.Sbom.Adapters/Adapters/ComponentDetection/PodComponentExtensions.cs index bef656520..36ceba0db 100644 --- a/src/Microsoft.Sbom.Adapters/Adapters/ComponentDetection/PodComponentExtensions.cs +++ b/src/Microsoft.Sbom.Adapters/Adapters/ComponentDetection/PodComponentExtensions.cs @@ -3,7 +3,6 @@ namespace Microsoft.Sbom.Adapters.ComponentDetection; -using System.Linq; using Microsoft.ComponentDetection.Contracts.TypedComponent; using Microsoft.Sbom.Contracts; @@ -31,6 +30,6 @@ internal static class PodComponentExtensions }, FilesAnalyzed = false, Type = "pod", - DependOn = component.AncestralReferrers?.Select(r => r.Id).ToList(), + DependOn = null }; } diff --git a/src/Microsoft.Sbom.Adapters/Adapters/ComponentDetection/RubyGemsComponentExtensions.cs b/src/Microsoft.Sbom.Adapters/Adapters/ComponentDetection/RubyGemsComponentExtensions.cs index 2e1e67aa7..6d9dacdf4 100644 --- a/src/Microsoft.Sbom.Adapters/Adapters/ComponentDetection/RubyGemsComponentExtensions.cs +++ b/src/Microsoft.Sbom.Adapters/Adapters/ComponentDetection/RubyGemsComponentExtensions.cs @@ -3,7 +3,6 @@ namespace Microsoft.Sbom.Adapters.ComponentDetection; -using System.Linq; using Microsoft.ComponentDetection.Contracts.TypedComponent; using Microsoft.Sbom.Contracts; @@ -33,6 +32,6 @@ internal static class RubyGemsComponentExtensions }, FilesAnalyzed = false, Type = "ruby", - DependOn = component.AncestralReferrers?.Select(r => r.Id).ToList(), + DependOn = null }; } diff --git a/src/Microsoft.Sbom.Api/Executors/ComponentDetectionBaseWalker.cs b/src/Microsoft.Sbom.Api/Executors/ComponentDetectionBaseWalker.cs index 997abe723..40f1d6e84 100644 --- a/src/Microsoft.Sbom.Api/Executors/ComponentDetectionBaseWalker.cs +++ b/src/Microsoft.Sbom.Api/Executors/ComponentDetectionBaseWalker.cs @@ -123,6 +123,8 @@ async Task Scan(string path) var uniqueComponents = FilterScannedComponents(scanResult); + uniqueComponents = ProcessDependencyGraphs(scanResult, uniqueComponents); + if (configuration.EnablePackageMetadataParsing?.Value == true) { if (uniqueComponents.Any()) @@ -217,4 +219,30 @@ async Task Scan(string path) } protected abstract IEnumerable FilterScannedComponents(ScanResult result); + + /// + /// Processes dependency graphs to filter components based on explicitly referenced component IDs. + /// + /// The scan result from component detection. + /// The collection of unique components to filter. + /// Filtered collection of components that are explicitly referenced in dependency graphs. + private IEnumerable ProcessDependencyGraphs(ScanResult scanResult, IEnumerable uniqueComponents) + { + var defaultGraphScanResult = scanResult as DefaultGraphScanResult; + if (defaultGraphScanResult != null && defaultGraphScanResult.DependencyGraphs != null) + { + // Collect all explicitly referenced component IDs from all dependency graphs + var explicitComponentIds = new HashSet(); + + foreach (var dependencyGraphPair in defaultGraphScanResult.DependencyGraphs) + { + var dependencyGraph = dependencyGraphPair.Value; + explicitComponentIds.UnionWith(dependencyGraph.ExplicitlyReferencedComponentIds); + } + + return uniqueComponents.Where(component => explicitComponentIds.Contains(component.Component.Id)); + } + + return uniqueComponents; + } } diff --git a/test/Microsoft.Sbom.Tool.Tests/IntegrationTests.cs b/test/Microsoft.Sbom.Tool.Tests/IntegrationTests.cs index 81d07d9eb..a323d3cbe 100644 --- a/test/Microsoft.Sbom.Tool.Tests/IntegrationTests.cs +++ b/test/Microsoft.Sbom.Tool.Tests/IntegrationTests.cs @@ -177,6 +177,27 @@ public void E2E_CompareSPDX22AndSPDX30Manifests_ComparisonAndDeterminismSucceeds Assert.AreEqual(SbomEqualityComparisonResult.Equal, areEqual, "The SPDX 2.2 and SPDX 3.0 manifests should be equivalent."); } + [TestMethod] + public void E2E_GenerateManifest_GeneratesNoTransitivePackagesAndDeps_ReturnsZeroExitCode() + { + if (!IsWindows) + { + Assert.Inconclusive("This test is not (yet) supported on non-Windows platforms."); + return; + } + + var testFolderPath = CreateTestFolder(); + GenerateManifestAndValidateSuccess(testFolderPath); + + var originalManifestFolderPath = AppendFullManifestFolderPath(testFolderPath); + var originalManifestFilePath = Path.Combine(AppendFullManifestFolderPath(testFolderPath), ManifestFileName); + + var jsonElement = ReadJsonFile(originalManifestFilePath); + var packages = jsonElement.GetProperty("packages"); + var relationships = jsonElement.GetProperty("relationships"); + Assert.AreEqual(packages.GetArrayLength(), relationships.GetArrayLength(), "The number of relationships should equal the number of packages."); + } + [TestMethod] public void E2E_GenerateAndRedactManifest_RedactedFileIsSmaller_ReturnsZeroExitCode() {