From a0e15204f2fa57224157016e0fd55eb019614db9 Mon Sep 17 00:00:00 2001 From: Paul Dorsch <107068277+pauld-msft@users.noreply.github.com> Date: Thu, 31 Oct 2024 11:29:37 -0400 Subject: [PATCH 01/10] Update nuget known limitations (#1295) Previous limitations was written before new nuget detector was rolled out. This clarifies some of the points and removes the indication that the new detector hasn't rolled out yet. --- docs/detectors/nuget.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/detectors/nuget.md b/docs/detectors/nuget.md index 972891531..4df9e35d7 100644 --- a/docs/detectors/nuget.md +++ b/docs/detectors/nuget.md @@ -20,8 +20,8 @@ NuGet Detection is performed by parsing any `*.nuspec`, `*.nupkg`, `*.packages.c ## Known Limitations -- The NuGet detector is currently overreporting because the global NuGet cache gets searched. This is because of NuGet's [restore behaviour][4] which downloads all possible dependencies before [resolving the final dependency graph][5]. To solve this overreporting a new NuGet Detector approach will be rolled out. This new approach will now only parse `*.packages.config` and `*.project.assets` (`*.csproj`) files. This means any components that are only found in `*.nuspec` or `*.nupkg` files will not be detected with the new NuGet Detector approach. -- There are also dependencies from the .NET SDK that are underreported. The list of dependencies can be found [here][6]. +- Any components that are only found in `*.nuspec` or `*.nupkg` files will not be detected with the latest NuGet Detector approach, because the NuGet detector that scans `*.nuspec` or `*.nupkg` files overreports. This is due to of NuGet's [restore behaviour][4] which downloads all possible dependencies before [resolving the final dependency graph][5]. +- Dependencies from the .NET SDK that are underreported. The list of dependencies can be found [here][6]. [4]: https://learn.microsoft.com/en-us/nuget/consume-packages/package-restore#package-restore-behavior [5]: https://learn.microsoft.com/en-us/nuget/concepts/dependency-resolution From c2546faf1eb476ed0a009a5e51074c03f88b6066 Mon Sep 17 00:00:00 2001 From: Eric StJohn Date: Thu, 31 Oct 2024 11:52:23 -0700 Subject: [PATCH 02/10] Add experimental NuGet detector for framework and dev dependencies (#1285) * Add experimental NuGet detector for framework and dev dependencies This PR does 3 things. 1. Adds `TargetFramework` to NuGet package references. This can be useful when querying component data to understand if components are used in a place where a vulnerability applies. 2. Adds _framework package_ handling. The .NET SDK will do [conflict resolution](https://github.com/dotnet/sdk/tree/main/src/Tasks/Common/ConflictResolution) and drop assets from packages that overlap with the framework. NuGet is planning to do the same https://github.com/NuGet/Home/issues/7344 but until then, it's beneficial to have component detection duplicate some of this logic. When a package is identified as overlapping with the framework we'll treat it as a Development Dependency so that it might be auto-dismissed. - .NETFramework projects do not get this - .NETFramework does not participate in conflict resolution by default. Even when enabled framework assemblies can be bypassed using bindingRedirects, or avoiding references to them. Due this fragility it's not safe to apply framework package rules to .NETFramework. - packages.config usage is also excluded since it precludes SDK conflict resolution (and is also only used on .NETFramework projects). 3. Recognizes `ExcludeAssets="Runtime"` usage as a Development Dependencies, also any packages which don't contribute to "runtime" will be developement dependencies. I reused _Development Dependency_ rather than plumbing a new concept. I only mapped data for the `Microsoft.NETCore.App` - the default shared framework. We could consider doing the same for `Microsoft.ASPNETCore.App` and `Microsoft.WindowsDesktop.App` but we'd need to plumb the reference information out of the assets file - currently that's not read and I'm not aware of a supported NuGet API for reading it (though it is present under `project/frameworks//frameworkReferences/` .NET Core 1.x has no data since it was packages itself. I have a fallback for future frameworks to read the data from the targeting packs. * Address feedback --- .../TypedComponent/NugetComponent.cs | 3 + .../FrameworkPackages/FrameworkPackages.cs | 122 +++++++ .../FrameworkPackages.net5.0.cs | 81 +++++ .../FrameworkPackages.net6.0.cs | 34 ++ .../FrameworkPackages.net7.0.cs | 26 ++ .../FrameworkPackages.net8.0.cs | 26 ++ .../FrameworkPackages.net9.0.cs | 98 ++++++ .../FrameworkPackages.netcoreapp2.0.cs | 49 +++ .../FrameworkPackages.netcoreapp2.1.cs | 25 ++ .../FrameworkPackages.netcoreapp2.2.cs | 15 + .../FrameworkPackages.netcoreapp3.0.cs | 49 +++ .../FrameworkPackages.netcoreapp3.1.cs | 27 ++ .../FrameworkPackages.netstandard2.0.cs | 108 ++++++ .../FrameworkPackages.netstandard2.1.cs | 48 +++ .../nuget/FrameworkPackages/Readme.md | 7 + ...tPackageReferenceFrameworkAwareDetector.cs | 223 +++++++++++++ .../nuget/NuGetPackagesConfigDetector.cs | 21 +- ...ectModelProjectCentricComponentDetector.cs | 9 + .../Configs/NuGetTargetFrameworkExperiment.cs | 22 ++ .../Extensions/ServiceCollectionExtensions.cs | 2 + ...ageReferenceFrameworkAwareDetectorTests.cs | 312 ++++++++++++++++++ 21 files changed, 1304 insertions(+), 3 deletions(-) create mode 100644 src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.cs create mode 100644 src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.net5.0.cs create mode 100644 src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.net6.0.cs create mode 100644 src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.net7.0.cs create mode 100644 src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.net8.0.cs create mode 100644 src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.net9.0.cs create mode 100644 src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp2.0.cs create mode 100644 src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp2.1.cs create mode 100644 src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp2.2.cs create mode 100644 src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp3.0.cs create mode 100644 src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp3.1.cs create mode 100644 src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netstandard2.0.cs create mode 100644 src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netstandard2.1.cs create mode 100644 src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/Readme.md create mode 100644 src/Microsoft.ComponentDetection.Detectors/nuget/NuGetPackageReferenceFrameworkAwareDetector.cs create mode 100644 src/Microsoft.ComponentDetection.Orchestrator/Experiments/Configs/NuGetTargetFrameworkExperiment.cs create mode 100644 test/Microsoft.ComponentDetection.Detectors.Tests/nuget/NuGetPackageReferenceFrameworkAwareDetectorTests.cs diff --git a/src/Microsoft.ComponentDetection.Contracts/TypedComponent/NugetComponent.cs b/src/Microsoft.ComponentDetection.Contracts/TypedComponent/NugetComponent.cs index dad787527..c335d7fd4 100644 --- a/src/Microsoft.ComponentDetection.Contracts/TypedComponent/NugetComponent.cs +++ b/src/Microsoft.ComponentDetection.Contracts/TypedComponent/NugetComponent.cs @@ -1,5 +1,6 @@ namespace Microsoft.ComponentDetection.Contracts.TypedComponent; +using System.Collections.Generic; using PackageUrl; public class NuGetComponent : TypedComponent @@ -22,6 +23,8 @@ public NuGetComponent(string name, string version, string[] authors = null) public string[] Authors { get; set; } + public ISet TargetFrameworks { get; set; } = new HashSet(); + public override ComponentType Type => ComponentType.NuGet; public override string Id => $"{this.Name} {this.Version} - {this.Type}"; diff --git a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.cs b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.cs new file mode 100644 index 000000000..b6a9c5da1 --- /dev/null +++ b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.cs @@ -0,0 +1,122 @@ +namespace Microsoft.ComponentDetection.Detectors.NuGet; + +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using global::NuGet.Frameworks; +using global::NuGet.Versioning; + +/// +/// Represents a set of packages that are provided by a specific framework. +/// At the moment this only represents the packages that are provided by the Microsoft.NETCore.App framework. +/// We could extend this to represent the packages provided by other frameworks like Microsoft.AspNetCore.App and Microsoft.WindowsDesktop.App. +/// +internal sealed partial class FrameworkPackages : IEnumerable>, IEnumerable +{ + private static readonly Dictionary FrameworkPackagesByFramework = []; + + static FrameworkPackages() + { + AddPackages(NETStandard20.Instance); + AddPackages(NETStandard21.Instance); + AddPackages(NETCoreApp20.Instance); + AddPackages(NETCoreApp21.Instance); + AddPackages(NETCoreApp22.Instance); + AddPackages(NETCoreApp30.Instance); + AddPackages(NETCoreApp31.Instance); + AddPackages(NETCoreApp50.Instance); + AddPackages(NETCoreApp60.Instance); + AddPackages(NETCoreApp70.Instance); + AddPackages(NETCoreApp80.Instance); + AddPackages(NETCoreApp90.Instance); + + static void AddPackages(FrameworkPackages packages) => FrameworkPackagesByFramework[packages.Framework] = packages; + } + + public FrameworkPackages(NuGetFramework framework) => this.Framework = framework; + + public FrameworkPackages(NuGetFramework framework, FrameworkPackages frameworkPackages) + : this(framework) => this.Packages = new(frameworkPackages.Packages); + + public NuGetFramework Framework { get; } + + public Dictionary Packages { get; } = new Dictionary(StringComparer.OrdinalIgnoreCase); + + public static FrameworkPackages GetFrameworkPackages(NuGetFramework framework) + { + if (FrameworkPackagesByFramework.TryGetValue(framework, out var frameworkPackages)) + { + return frameworkPackages; + } + + // if we didn't predefine the package overrides, load them from the targeting pack + // we might just leave this out since in future frameworks we'll have this functionality built into NuGet. + var frameworkPackagesFromPack = LoadFrameworkPackagesFromPack(framework); + + return FrameworkPackagesByFramework[framework] = frameworkPackagesFromPack ?? new FrameworkPackages(framework); + } + + private static FrameworkPackages LoadFrameworkPackagesFromPack(NuGetFramework framework) + { + if (framework is null || framework.Framework != FrameworkConstants.FrameworkIdentifiers.NetCoreApp) + { + return null; + } + + // packs location : %ProgramFiles%\dotnet\packs + var packsFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "dotnet", "packs", "Microsoft.NETCore.App.Ref"); + if (!Directory.Exists(packsFolder)) + { + return null; + } + + var packVersionPattern = $"{framework.Version.Major}.{framework.Version.Minor}.*"; + var packDirectories = Directory.GetDirectories(packsFolder, packVersionPattern); + var packageOverridesFile = packDirectories + .Select(d => (Overrides: Path.Combine(d, "data", "PackageOverrides.txt"), Version: ParseVersion(Path.GetFileName(d)))) + .Where(d => File.Exists(d.Overrides)) + .OrderByDescending(d => d.Version) + .FirstOrDefault().Overrides; + + if (packageOverridesFile == null) + { + // we should also try to grab them from the user's package folder - they'll be in one location or the other. + return null; + } + + // Adapted from https://github.com/dotnet/sdk/blob/c3a8f72c3a5491c693ff8e49e7406136a12c3040/src/Tasks/Common/ConflictResolution/PackageOverride.cs#L52-L68 + var frameworkPackages = new FrameworkPackages(framework); + var packageOverrides = File.ReadAllLines(packageOverridesFile); + + foreach (var packageOverride in packageOverrides) + { + var packageOverrideParts = packageOverride.Trim().Split('|'); + + if (packageOverrideParts.Length == 2) + { + var packageId = packageOverrideParts[0]; + var packageVersion = ParseVersion(packageOverrideParts[1]); + + frameworkPackages.Packages[packageId] = packageVersion; + } + } + + return frameworkPackages; + + static NuGetVersion ParseVersion(string versionString) => NuGetVersion.TryParse(versionString, out var version) ? version : null; + } + + private void Add(string id, string version) + { + // intentionally redirect to indexer to allow for overwrite + this.Packages[id] = NuGetVersion.Parse(version); + } + + public bool IsAFrameworkComponent(string id, NuGetVersion version) => this.Packages.TryGetValue(id, out var frameworkPackageVersion) && frameworkPackageVersion >= version; + + IEnumerator> IEnumerable>.GetEnumerator() => this.Packages.GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException(); +} diff --git a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.net5.0.cs b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.net5.0.cs new file mode 100644 index 000000000..0326c7dfb --- /dev/null +++ b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.net5.0.cs @@ -0,0 +1,81 @@ +namespace Microsoft.ComponentDetection.Detectors.NuGet; + +using global::NuGet.Frameworks; + +/// +/// Framework packages for net5.0. +/// +internal partial class FrameworkPackages +{ + internal static class NETCoreApp50 + { + internal static FrameworkPackages Instance { get; } = new(NuGetFramework.Parse("net5.0"), NETCoreApp31.Instance) + { + { "Microsoft.CSharp", "4.7.0" }, + { "runtime.debian.8-x64.runtime.native.System", "4.3.0" }, + { "runtime.debian.8-x64.runtime.native.System.IO.Compression", "4.3.0" }, + { "runtime.debian.8-x64.runtime.native.System.Net.Http", "4.3.0" }, + { "runtime.debian.8-x64.runtime.native.System.Net.Security", "4.3.0" }, + { "runtime.debian.8-x64.runtime.native.System.Security.Cryptography", "4.3.0" }, + { "runtime.fedora.23-x64.runtime.native.System", "4.3.0" }, + { "runtime.fedora.23-x64.runtime.native.System.IO.Compression", "4.3.0" }, + { "runtime.fedora.23-x64.runtime.native.System.Net.Http", "4.3.0" }, + { "runtime.fedora.23-x64.runtime.native.System.Net.Security", "4.3.0" }, + { "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography", "4.3.0" }, + { "runtime.fedora.24-x64.runtime.native.System", "4.3.0" }, + { "runtime.fedora.24-x64.runtime.native.System.IO.Compression", "4.3.0" }, + { "runtime.fedora.24-x64.runtime.native.System.Net.Http", "4.3.0" }, + { "runtime.fedora.24-x64.runtime.native.System.Net.Security", "4.3.0" }, + { "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography", "4.3.0" }, + { "runtime.opensuse.13.2-x64.runtime.native.System", "4.3.0" }, + { "runtime.opensuse.13.2-x64.runtime.native.System.IO.Compression", "4.3.0" }, + { "runtime.opensuse.13.2-x64.runtime.native.System.Net.Http", "4.3.0" }, + { "runtime.opensuse.13.2-x64.runtime.native.System.Net.Security", "4.3.0" }, + { "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography", "4.3.0" }, + { "runtime.opensuse.42.1-x64.runtime.native.System", "4.3.0" }, + { "runtime.opensuse.42.1-x64.runtime.native.System.IO.Compression", "4.3.0" }, + { "runtime.opensuse.42.1-x64.runtime.native.System.Net.Http", "4.3.0" }, + { "runtime.opensuse.42.1-x64.runtime.native.System.Net.Security", "4.3.0" }, + { "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography", "4.3.0" }, + { "runtime.osx.10.10-x64.runtime.native.System", "4.3.0" }, + { "runtime.osx.10.10-x64.runtime.native.System.IO.Compression", "4.3.0" }, + { "runtime.osx.10.10-x64.runtime.native.System.Net.Http", "4.3.0" }, + { "runtime.osx.10.10-x64.runtime.native.System.Net.Security", "4.3.0" }, + { "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography", "4.3.0" }, + { "runtime.rhel.7-x64.runtime.native.System", "4.3.0" }, + { "runtime.rhel.7-x64.runtime.native.System.IO.Compression", "4.3.0" }, + { "runtime.rhel.7-x64.runtime.native.System.Net.Http", "4.3.0" }, + { "runtime.rhel.7-x64.runtime.native.System.Net.Security", "4.3.0" }, + { "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography", "4.3.0" }, + { "runtime.ubuntu.14.04-x64.runtime.native.System", "4.3.0" }, + { "runtime.ubuntu.14.04-x64.runtime.native.System.IO.Compression", "4.3.0" }, + { "runtime.ubuntu.14.04-x64.runtime.native.System.Net.Http", "4.3.0" }, + { "runtime.ubuntu.14.04-x64.runtime.native.System.Net.Security", "4.3.0" }, + { "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography", "4.3.0" }, + { "runtime.ubuntu.16.04-x64.runtime.native.System", "4.3.0" }, + { "runtime.ubuntu.16.04-x64.runtime.native.System.IO.Compression", "4.3.0" }, + { "runtime.ubuntu.16.04-x64.runtime.native.System.Net.Http", "4.3.0" }, + { "runtime.ubuntu.16.04-x64.runtime.native.System.Net.Security", "4.3.0" }, + { "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography", "4.3.0" }, + { "runtime.ubuntu.16.10-x64.runtime.native.System", "4.3.0" }, + { "runtime.ubuntu.16.10-x64.runtime.native.System.IO.Compression", "4.3.0" }, + { "runtime.ubuntu.16.10-x64.runtime.native.System.Net.Http", "4.3.0" }, + { "runtime.ubuntu.16.10-x64.runtime.native.System.Net.Security", "4.3.0" }, + { "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography", "4.3.0" }, + { "System.Buffers", "4.5.1" }, + { "System.Collections.Immutable", "5.0.0" }, + { "System.ComponentModel.Annotations", "5.0.0" }, + { "System.Diagnostics.DiagnosticSource", "5.0.0" }, + { "System.Formats.Asn1", "5.0.0" }, + { "System.Net.Http.Json", "5.0.0" }, + { "System.Reflection.DispatchProxy", "4.7.1" }, + { "System.Reflection.Metadata", "5.0.0" }, + { "System.Runtime.CompilerServices.Unsafe", "5.0.0" }, + { "System.Text.Encoding.CodePages", "5.0.0" }, + { "System.Text.Encodings.Web", "5.0.0" }, + { "System.Text.Json", "5.0.0" }, + { "System.Threading.Channels", "5.0.0" }, + { "System.Threading.Tasks.Dataflow", "5.0.0" }, + }; + } +} diff --git a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.net6.0.cs b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.net6.0.cs new file mode 100644 index 000000000..ca5b2d92b --- /dev/null +++ b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.net6.0.cs @@ -0,0 +1,34 @@ +namespace Microsoft.ComponentDetection.Detectors.NuGet; + +using global::NuGet.Frameworks; + +/// +/// Framework packages for net6.0. +/// +internal partial class FrameworkPackages +{ + internal static class NETCoreApp60 + { + internal static FrameworkPackages Instance { get; } = new(NuGetFramework.Parse("net6.0"), NETCoreApp50.Instance) + { + { "Microsoft.Win32.Registry", "5.0.0" }, + { "System.Collections.Immutable", "6.0.0" }, + { "System.Diagnostics.DiagnosticSource", "6.0.1" }, + { "System.Formats.Asn1", "6.0.1" }, + { "System.IO.FileSystem.AccessControl", "5.0.0" }, + { "System.IO.Pipes.AccessControl", "5.0.0" }, + { "System.Net.Http.Json", "6.0.1" }, + { "System.Reflection.Metadata", "6.0.1" }, + { "System.Runtime.CompilerServices.Unsafe", "6.0.0" }, + { "System.Security.AccessControl", "6.0.1" }, + { "System.Security.Cryptography.Cng", "5.0.0" }, + { "System.Security.Cryptography.OpenSsl", "5.0.0" }, + { "System.Security.Principal.Windows", "5.0.0" }, + { "System.Text.Encoding.CodePages", "6.0.0" }, + { "System.Text.Encodings.Web", "6.0.0" }, + { "System.Text.Json", "6.0.9" }, + { "System.Threading.Channels", "6.0.0" }, + { "System.Threading.Tasks.Dataflow", "6.0.0" }, + }; + } +} diff --git a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.net7.0.cs b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.net7.0.cs new file mode 100644 index 000000000..206d1a194 --- /dev/null +++ b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.net7.0.cs @@ -0,0 +1,26 @@ +namespace Microsoft.ComponentDetection.Detectors.NuGet; + +using global::NuGet.Frameworks; + +/// +/// Framework packages for net7.0. +/// +internal partial class FrameworkPackages +{ + internal static class NETCoreApp70 + { + internal static FrameworkPackages Instance { get; } = new(NuGetFramework.Parse("net7.0"), NETCoreApp60.Instance) + { + { "System.Collections.Immutable", "7.0.0" }, + { "System.Diagnostics.DiagnosticSource", "7.0.2" }, + { "System.Formats.Asn1", "7.0.0" }, + { "System.Net.Http.Json", "7.0.1" }, + { "System.Reflection.Metadata", "7.0.2" }, + { "System.Text.Encoding.CodePages", "7.0.0" }, + { "System.Text.Encodings.Web", "7.0.0" }, + { "System.Text.Json", "7.0.4" }, + { "System.Threading.Channels", "7.0.0" }, + { "System.Threading.Tasks.Dataflow", "7.0.0" }, + }; + } +} diff --git a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.net8.0.cs b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.net8.0.cs new file mode 100644 index 000000000..86a273591 --- /dev/null +++ b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.net8.0.cs @@ -0,0 +1,26 @@ +namespace Microsoft.ComponentDetection.Detectors.NuGet; + +using global::NuGet.Frameworks; + +/// +/// Framework packages for net8.0. +/// +internal partial class FrameworkPackages +{ + internal static class NETCoreApp80 + { + internal static FrameworkPackages Instance { get; } = new(NuGetFramework.Parse("net8.0"), NETCoreApp70.Instance) + { + { "System.Collections.Immutable", "8.0.0" }, + { "System.Diagnostics.DiagnosticSource", "8.0.1" }, + { "System.Formats.Asn1", "8.0.1" }, + { "System.Net.Http.Json", "8.0.0" }, + { "System.Reflection.Metadata", "8.0.0" }, + { "System.Text.Encoding.CodePages", "8.0.0" }, + { "System.Text.Encodings.Web", "8.0.0" }, + { "System.Text.Json", "8.0.4" }, + { "System.Threading.Channels", "8.0.0" }, + { "System.Threading.Tasks.Dataflow", "8.0.1" }, + }; + } +} diff --git a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.net9.0.cs b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.net9.0.cs new file mode 100644 index 000000000..484c7e8a3 --- /dev/null +++ b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.net9.0.cs @@ -0,0 +1,98 @@ +namespace Microsoft.ComponentDetection.Detectors.NuGet; + +using global::NuGet.Frameworks; + +/// +/// Framework packages for net9.0. +/// +internal partial class FrameworkPackages +{ + internal static class NETCoreApp90 + { + internal static FrameworkPackages Instance { get; } = new(NuGetFramework.Parse("net9.0"), NETCoreApp80.Instance) + { + { "Microsoft.VisualBasic", "10.4.0" }, + { "runtime.debian.8-x64.runtime.native.System", "4.3.1" }, + { "runtime.debian.8-x64.runtime.native.System.IO.Compression", "4.3.2" }, + { "runtime.debian.8-x64.runtime.native.System.Net.Http", "4.3.1" }, + { "runtime.debian.8-x64.runtime.native.System.Net.Security", "4.3.1" }, + { "runtime.debian.8-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, + { "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, + { "runtime.fedora.23-x64.runtime.native.System", "4.3.1" }, + { "runtime.fedora.23-x64.runtime.native.System.IO.Compression", "4.3.2" }, + { "runtime.fedora.23-x64.runtime.native.System.Net.Http", "4.3.1" }, + { "runtime.fedora.23-x64.runtime.native.System.Net.Security", "4.3.1" }, + { "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, + { "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, + { "runtime.fedora.24-x64.runtime.native.System", "4.3.1" }, + { "runtime.fedora.24-x64.runtime.native.System.IO.Compression", "4.3.2" }, + { "runtime.fedora.24-x64.runtime.native.System.Net.Http", "4.3.1" }, + { "runtime.fedora.24-x64.runtime.native.System.Net.Security", "4.3.1" }, + { "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, + { "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, + { "runtime.opensuse.13.2-x64.runtime.native.System", "4.3.1" }, + { "runtime.opensuse.13.2-x64.runtime.native.System.IO.Compression", "4.3.2" }, + { "runtime.opensuse.13.2-x64.runtime.native.System.Net.Http", "4.3.1" }, + { "runtime.opensuse.13.2-x64.runtime.native.System.Net.Security", "4.3.1" }, + { "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, + { "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, + { "runtime.opensuse.42.1-x64.runtime.native.System", "4.3.1" }, + { "runtime.opensuse.42.1-x64.runtime.native.System.IO.Compression", "4.3.2" }, + { "runtime.opensuse.42.1-x64.runtime.native.System.Net.Http", "4.3.1" }, + { "runtime.opensuse.42.1-x64.runtime.native.System.Net.Security", "4.3.1" }, + { "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, + { "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, + { "runtime.osx.10.10-x64.runtime.native.System", "4.3.1" }, + { "runtime.osx.10.10-x64.runtime.native.System.IO.Compression", "4.3.2" }, + { "runtime.osx.10.10-x64.runtime.native.System.Net.Http", "4.3.1" }, + { "runtime.osx.10.10-x64.runtime.native.System.Net.Security", "4.3.1" }, + { "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, + { "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple", "4.3.1" }, + { "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, + { "runtime.rhel.7-x64.runtime.native.System", "4.3.1" }, + { "runtime.rhel.7-x64.runtime.native.System.IO.Compression", "4.3.2" }, + { "runtime.rhel.7-x64.runtime.native.System.Net.Http", "4.3.1" }, + { "runtime.rhel.7-x64.runtime.native.System.Net.Security", "4.3.1" }, + { "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, + { "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, + { "runtime.ubuntu.14.04-x64.runtime.native.System", "4.3.1" }, + { "runtime.ubuntu.14.04-x64.runtime.native.System.IO.Compression", "4.3.2" }, + { "runtime.ubuntu.14.04-x64.runtime.native.System.Net.Http", "4.3.1" }, + { "runtime.ubuntu.14.04-x64.runtime.native.System.Net.Security", "4.3.1" }, + { "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, + { "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, + { "runtime.ubuntu.16.04-x64.runtime.native.System", "4.3.1" }, + { "runtime.ubuntu.16.04-x64.runtime.native.System.IO.Compression", "4.3.2" }, + { "runtime.ubuntu.16.04-x64.runtime.native.System.Net.Http", "4.3.1" }, + { "runtime.ubuntu.16.04-x64.runtime.native.System.Net.Security", "4.3.1" }, + { "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, + { "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, + { "runtime.ubuntu.16.10-x64.runtime.native.System", "4.3.1" }, + { "runtime.ubuntu.16.10-x64.runtime.native.System.IO.Compression", "4.3.2" }, + { "runtime.ubuntu.16.10-x64.runtime.native.System.Net.Http", "4.3.1" }, + { "runtime.ubuntu.16.10-x64.runtime.native.System.Net.Security", "4.3.1" }, + { "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, + { "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, + { "System.Buffers", "5.0.0" }, + { "System.Collections.Immutable", "9.0.0" }, + { "System.Diagnostics.DiagnosticSource", "9.0.0" }, + { "System.Formats.Asn1", "9.0.0" }, + { "System.Formats.Tar", "9.0.0" }, + { "System.IO.Pipelines", "9.0.0" }, + { "System.Memory", "5.0.0" }, + { "System.Net.Http.Json", "9.0.0" }, + { "System.Numerics.Vectors", "5.0.0" }, + { "System.Private.Uri", "4.3.2" }, + { "System.Reflection.DispatchProxy", "6.0.0" }, + { "System.Reflection.Metadata", "9.0.0" }, + { "System.Runtime.CompilerServices.Unsafe", "7.0.0" }, + { "System.Text.Encoding.CodePages", "9.0.0" }, + { "System.Text.Encodings.Web", "9.0.0" }, + { "System.Text.Json", "9.0.0" }, + { "System.Threading.Channels", "9.0.0" }, + { "System.Threading.Tasks.Dataflow", "9.0.0" }, + { "System.Threading.Tasks.Extensions", "5.0.0" }, + { "System.Xml.XPath.XDocument", "5.0.0" }, + }; + } +} diff --git a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp2.0.cs b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp2.0.cs new file mode 100644 index 000000000..dc934febf --- /dev/null +++ b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp2.0.cs @@ -0,0 +1,49 @@ +namespace Microsoft.ComponentDetection.Detectors.NuGet; + +using global::NuGet.Frameworks; + +/// +/// Framework packages for .NETCoreApp,Version=v2.0. +/// +internal partial class FrameworkPackages +{ + internal static class NETCoreApp20 + { + internal static FrameworkPackages Instance { get; } = new(NuGetFramework.Parse("netcoreapp2.0"), NETStandard20.Instance) + { + { "System.Buffers", "4.4.0" }, + { "System.Collections.Concurrent", "4.3.0" }, + { "System.Collections.Immutable", "1.4.0" }, + { "System.ComponentModel", "4.3.0" }, + { "System.ComponentModel.Annotations", "4.4.0" }, + { "System.ComponentModel.EventBasedAsync", "4.3.0" }, + { "System.Diagnostics.Contracts", "4.3.0" }, + { "System.Diagnostics.DiagnosticSource", "4.4.1" }, + { "System.Dynamic.Runtime", "4.3.0" }, + { "System.Linq.Parallel", "4.3.0" }, + { "System.Linq.Queryable", "4.3.0" }, + { "System.Net.Requests", "4.3.0" }, + { "System.Net.WebHeaderCollection", "4.3.0" }, + { "System.Numerics.Vectors", "4.4.0" }, + { "System.ObjectModel", "4.3.0" }, + { "System.Reflection.DispatchProxy", "4.4.0" }, + { "System.Reflection.Emit", "4.7.0" }, + { "System.Reflection.Emit.ILGeneration", "4.7.0" }, + { "System.Reflection.Emit.Lightweight", "4.7.0" }, + { "System.Reflection.Metadata", "1.5.0" }, + { "System.Reflection.TypeExtensions", "4.7.0" }, + { "System.Runtime.InteropServices.WindowsRuntime", "4.3.0" }, + { "System.Runtime.Loader", "4.3.0" }, + { "System.Runtime.Numerics", "4.3.0" }, + { "System.Runtime.Serialization.Json", "4.3.0" }, + { "System.Security.Principal", "4.3.0" }, + { "System.Text.RegularExpressions", "4.3.1" }, + { "System.Threading", "4.3.0" }, + { "System.Threading.Tasks.Dataflow", "4.8.0" }, + { "System.Threading.Tasks.Extensions", "4.4.0" }, + { "System.Threading.Tasks.Parallel", "4.3.0" }, + { "System.Xml.XDocument", "4.3.0" }, + { "System.Xml.XmlSerializer", "4.3.0" }, + }; + } +} diff --git a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp2.1.cs b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp2.1.cs new file mode 100644 index 000000000..ef5489f50 --- /dev/null +++ b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp2.1.cs @@ -0,0 +1,25 @@ +namespace Microsoft.ComponentDetection.Detectors.NuGet; + +using global::NuGet.Frameworks; + +/// +/// Framework packages for .NETCoreApp,Version=v2.1. +/// +internal partial class FrameworkPackages +{ + internal static class NETCoreApp21 + { + internal static FrameworkPackages Instance { get; } = new(NuGetFramework.Parse("netcoreapp2.1"), NETCoreApp20.Instance) + { + { "System.Collections.Immutable", "1.5.0" }, + { "System.ComponentModel.Annotations", "4.4.1" }, + { "System.Diagnostics.DiagnosticSource", "4.5.0" }, + { "System.Memory", "4.5.5" }, + { "System.Reflection.DispatchProxy", "4.5.0" }, + { "System.Reflection.Metadata", "1.6.0" }, + { "System.Threading.Tasks.Dataflow", "4.9.0" }, + { "System.Threading.Tasks.Extensions", "4.5.4" }, + { "System.ValueTuple", "4.5.0" }, + }; + } +} diff --git a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp2.2.cs b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp2.2.cs new file mode 100644 index 000000000..d9fa440fa --- /dev/null +++ b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp2.2.cs @@ -0,0 +1,15 @@ +namespace Microsoft.ComponentDetection.Detectors.NuGet; + +using global::NuGet.Frameworks; + +/// +/// Framework packages for .NETCoreApp,Version=v2.2. +/// +internal partial class FrameworkPackages +{ + internal static class NETCoreApp22 + { + // .NETCore 2.2 was the same as .NETCore 2.1 + internal static FrameworkPackages Instance { get; } = new(NuGetFramework.Parse("netcoreapp2.2"), NETCoreApp21.Instance); + } +} diff --git a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp3.0.cs b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp3.0.cs new file mode 100644 index 000000000..84f3c854d --- /dev/null +++ b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp3.0.cs @@ -0,0 +1,49 @@ +namespace Microsoft.ComponentDetection.Detectors.NuGet; + +using global::NuGet.Frameworks; + +/// +/// Framework packages for .NETCoreApp,Version=v3.0. +/// +internal partial class FrameworkPackages +{ + internal static class NETCoreApp30 + { + internal static FrameworkPackages Instance { get; } = new(NuGetFramework.Parse("netcoreapp3.0"), NETCoreApp21.Instance) + { + { "Microsoft.CSharp", "4.4.0" }, + { "Microsoft.Win32.Registry", "4.4.0" }, + { "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.0" }, + { "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.0" }, + { "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.0" }, + { "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.0" }, + { "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.0" }, + { "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple", "4.3.0" }, + { "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.0" }, + { "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.0" }, + { "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.0" }, + { "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.0" }, + { "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.0" }, + { "System.Collections.Immutable", "1.6.0" }, + { "System.ComponentModel.Annotations", "4.6.0" }, + { "System.Data.DataSetExtensions", "4.5.0" }, + { "System.Diagnostics.DiagnosticSource", "4.6.0" }, + { "System.IO.FileSystem.AccessControl", "4.4.0" }, + { "System.Numerics.Vectors", "4.5.0" }, + { "System.Private.DataContractSerialization", "4.3.0" }, + { "System.Reflection.DispatchProxy", "4.6.0" }, + { "System.Reflection.Metadata", "1.7.0" }, + { "System.Runtime.CompilerServices.Unsafe", "4.6.0" }, + { "System.Security.AccessControl", "4.4.0" }, + { "System.Security.Cryptography.Cng", "4.4.0" }, + { "System.Security.Cryptography.OpenSsl", "4.4.0" }, + { "System.Security.Cryptography.Xml", "4.4.0" }, + { "System.Security.Principal.Windows", "4.4.0" }, + { "System.Text.Encoding.CodePages", "4.6.0" }, + { "System.Text.Encodings.Web", "4.6.0" }, + { "System.Text.Json", "4.6.0" }, + { "System.Threading.Channels", "4.6.0" }, + { "System.Threading.Tasks.Dataflow", "4.10.0" }, + }; + } +} diff --git a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp3.1.cs b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp3.1.cs new file mode 100644 index 000000000..f7f879843 --- /dev/null +++ b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp3.1.cs @@ -0,0 +1,27 @@ +namespace Microsoft.ComponentDetection.Detectors.NuGet; + +using global::NuGet.Frameworks; + +/// +/// Framework packages for .NETCoreApp,Version=v3.1. +/// +internal partial class FrameworkPackages +{ + internal static class NETCoreApp31 + { + internal static FrameworkPackages Instance { get; } = new(NuGetFramework.Parse("netcoreapp3.1"), NETCoreApp30.Instance) + { + { "System.Collections.Immutable", "1.7.0" }, + { "System.ComponentModel.Annotations", "4.7.0" }, + { "System.Diagnostics.DiagnosticSource", "4.7.0" }, + { "System.Reflection.DispatchProxy", "4.7.0" }, + { "System.Reflection.Metadata", "1.8.0" }, + { "System.Runtime.CompilerServices.Unsafe", "4.7.1" }, + { "System.Text.Encoding.CodePages", "4.7.0" }, + { "System.Text.Encodings.Web", "4.7.0" }, + { "System.Text.Json", "4.7.0" }, + { "System.Threading.Channels", "4.7.0" }, + { "System.Threading.Tasks.Dataflow", "4.11.0" }, + }; + } +} diff --git a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netstandard2.0.cs b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netstandard2.0.cs new file mode 100644 index 000000000..8095fb527 --- /dev/null +++ b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netstandard2.0.cs @@ -0,0 +1,108 @@ +namespace Microsoft.ComponentDetection.Detectors.NuGet; + +using global::NuGet.Frameworks; + +/// +/// Framework packages for .NETStandard,Version=v2.0. +/// +internal partial class FrameworkPackages +{ + internal static class NETStandard20 + { + internal static FrameworkPackages Instance { get; } = new(NuGetFramework.Parse("netstandard2.0")) + { + { "Microsoft.Win32.Primitives", "4.3.0" }, + { "System.AppContext", "4.3.0" }, + { "System.Collections", "4.3.0" }, + { "System.Collections.NonGeneric", "4.3.0" }, + { "System.Collections.Specialized", "4.3.0" }, + { "System.ComponentModel", "4.0.1" }, + { "System.ComponentModel.EventBasedAsync", "4.0.11" }, + { "System.ComponentModel.Primitives", "4.3.0" }, + { "System.ComponentModel.TypeConverter", "4.3.0" }, + { "System.Console", "4.3.1" }, + { "System.Data.Common", "4.3.0" }, + { "System.Diagnostics.Contracts", "4.0.1" }, + { "System.Diagnostics.Debug", "4.3.0" }, + { "System.Diagnostics.FileVersionInfo", "4.3.0" }, + { "System.Diagnostics.Process", "4.3.0" }, + { "System.Diagnostics.StackTrace", "4.3.0" }, + { "System.Diagnostics.TextWriterTraceListener", "4.3.0" }, + { "System.Diagnostics.Tools", "4.3.0" }, + { "System.Diagnostics.TraceSource", "4.3.0" }, + { "System.Diagnostics.Tracing", "4.3.0" }, + { "System.Drawing.Primitives", "4.3.0" }, + { "System.Dynamic.Runtime", "4.0.11" }, + { "System.Globalization", "4.3.0" }, + { "System.Globalization.Calendars", "4.3.0" }, + { "System.Globalization.Extensions", "4.3.0" }, + { "System.IO", "4.3.0" }, + { "System.IO.Compression", "4.3.0" }, + { "System.IO.Compression.ZipFile", "4.3.0" }, + { "System.IO.FileSystem", "4.3.0" }, + { "System.IO.FileSystem.DriveInfo", "4.3.1" }, + { "System.IO.FileSystem.Primitives", "4.3.0" }, + { "System.IO.FileSystem.Watcher", "4.3.0" }, + { "System.IO.IsolatedStorage", "4.3.0" }, + { "System.IO.MemoryMappedFiles", "4.3.0" }, + { "System.IO.Pipes", "4.3.0" }, + { "System.IO.UnmanagedMemoryStream", "4.3.0" }, + { "System.Linq", "4.3.0" }, + { "System.Linq.Expressions", "4.3.0" }, + { "System.Linq.Parallel", "4.0.1" }, + { "System.Linq.Queryable", "4.0.1" }, + { "System.Net.Http", "4.3.4" }, + { "System.Net.NameResolution", "4.3.0" }, + { "System.Net.NetworkInformation", "4.3.0" }, + { "System.Net.Ping", "4.3.0" }, + { "System.Net.Primitives", "4.3.1" }, + { "System.Net.Requests", "4.0.11" }, + { "System.Net.Security", "4.3.2" }, + { "System.Net.Sockets", "4.3.0" }, + { "System.Net.WebHeaderCollection", "4.0.1" }, + { "System.Net.WebSockets", "4.3.0" }, + { "System.Net.WebSockets.Client", "4.3.2" }, + { "System.Reflection", "4.3.0" }, + { "System.Reflection.Extensions", "4.3.0" }, + { "System.Reflection.Primitives", "4.3.0" }, + { "System.Resources.Reader", "4.3.0" }, + { "System.Resources.ResourceManager", "4.3.0" }, + { "System.Resources.Writer", "4.3.0" }, + { "System.Runtime", "4.3.1" }, + { "System.Runtime.CompilerServices.VisualC", "4.3.0" }, + { "System.Runtime.Extensions", "4.3.1" }, + { "System.Runtime.Handles", "4.3.0" }, + { "System.Runtime.InteropServices", "4.3.0" }, + { "System.Runtime.InteropServices.RuntimeInformation", "4.3.0" }, + { "System.Runtime.Numerics", "4.0.1" }, + { "System.Runtime.Serialization.Formatters", "4.3.0" }, + { "System.Runtime.Serialization.Primitives", "4.3.0" }, + { "System.Runtime.Serialization.Xml", "4.3.0" }, + { "System.Security.Claims", "4.3.0" }, + { "System.Security.Cryptography.Algorithms", "4.3.1" }, + { "System.Security.Cryptography.Csp", "4.3.0" }, + { "System.Security.Cryptography.Encoding", "4.3.0" }, + { "System.Security.Cryptography.Primitives", "4.3.0" }, + { "System.Security.Cryptography.X509Certificates", "4.3.2" }, + { "System.Security.Principal", "4.0.1" }, + { "System.Security.SecureString", "4.3.0" }, + { "System.Text.Encoding", "4.3.0" }, + { "System.Text.Encoding.Extensions", "4.3.0" }, + { "System.Text.RegularExpressions", "4.3.0" }, + { "System.Threading", "4.0.11" }, + { "System.Threading.Overlapped", "4.3.0" }, + { "System.Threading.Tasks", "4.3.0" }, + { "System.Threading.Tasks.Parallel", "4.0.1" }, + { "System.Threading.Thread", "4.3.0" }, + { "System.Threading.ThreadPool", "4.3.0" }, + { "System.Threading.Timer", "4.3.0" }, + { "System.ValueTuple", "4.4.0" }, + { "System.Xml.ReaderWriter", "4.3.1" }, + { "System.Xml.XDocument", "4.0.11" }, + { "System.Xml.XmlDocument", "4.3.0" }, + { "System.Xml.XmlSerializer", "4.0.11" }, + { "System.Xml.XPath", "4.3.0" }, + { "System.Xml.XPath.XDocument", "4.3.0" }, + }; + } +} diff --git a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netstandard2.1.cs b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netstandard2.1.cs new file mode 100644 index 000000000..9d5b2bc00 --- /dev/null +++ b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netstandard2.1.cs @@ -0,0 +1,48 @@ +namespace Microsoft.ComponentDetection.Detectors.NuGet; + +using global::NuGet.Frameworks; + +/// +/// Framework packages for .NETStandard,Version=v2.1. +/// +internal partial class FrameworkPackages +{ + internal static class NETStandard21 + { + internal static FrameworkPackages Instance { get; } = new(NuGetFramework.Parse("netstandard2.1"), NETStandard20.Instance) + { + { "System.Buffers", "4.5.1" }, + { "System.Collections.Concurrent", "4.3.0" }, + { "System.Collections.Immutable", "1.4.0" }, + { "System.ComponentModel", "4.3.0" }, + { "System.ComponentModel.Composition", "4.5.0" }, + { "System.ComponentModel.EventBasedAsync", "4.3.0" }, + { "System.Diagnostics.Contracts", "4.3.0" }, + { "System.Dynamic.Runtime", "4.3.0" }, + { "System.Linq.Queryable", "4.3.0" }, + { "System.Memory", "4.5.5" }, + { "System.Net.Requests", "4.3.0" }, + { "System.Net.WebHeaderCollection", "4.3.0" }, + { "System.Numerics.Vectors", "4.5.0" }, + { "System.ObjectModel", "4.3.0" }, + { "System.Private.DataContractSerialization", "4.3.0" }, + { "System.Reflection.DispatchProxy", "4.5.1" }, + { "System.Reflection.Emit", "4.7.0" }, + { "System.Reflection.Emit.ILGeneration", "4.7.0" }, + { "System.Reflection.Emit.Lightweight", "4.7.0" }, + { "System.Reflection.TypeExtensions", "4.3.0" }, + { "System.Runtime.Loader", "4.3.0" }, + { "System.Runtime.Numerics", "4.3.0" }, + { "System.Runtime.Serialization.Json", "4.3.0" }, + { "System.Security.AccessControl", "4.4.0" }, + { "System.Security.Cryptography.Xml", "4.4.0" }, + { "System.Security.Principal", "4.3.0" }, + { "System.Security.Principal.Windows", "4.4.0" }, + { "System.Threading", "4.3.0" }, + { "System.Threading.Tasks.Extensions", "4.5.4" }, + { "System.Threading.Tasks.Parallel", "4.3.0" }, + { "System.Xml.XDocument", "4.3.0" }, + { "System.Xml.XmlSerializer", "4.3.0" }, + }; + } +} diff --git a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/Readme.md b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/Readme.md new file mode 100644 index 000000000..7b7b0982b --- /dev/null +++ b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/Readme.md @@ -0,0 +1,7 @@ +The .NET SDK does conflict resolution with NuGet packages to decide when to ignore the content of packages in favor of that from other sources (like other packages or the Framework itself). + +Since packages are immutable - we can precompute what packages will "lose" to framework assets. These lists were calculated with a tool that downloads packages, resolve what assets apply for a given frameowrk, then compares those to the framework's reference assemblies. + +The framework targeting packs have a file to ship these precomputed package versions, [PackageOverrides.txt](https://github.com/dotnet/sdk/blob/7deb36232b9c0ccd5084fced1df07920c10a5b72/src/Tasks/Microsoft.NET.Build.Tasks/ResolveTargetingPackAssets.cs#L199) -- but that file wasn't kept up to date of the course framework versions. It was meant as a "fast path" not a source of truth. In future framework versions this will need to be the source of truth since it will feed into NuGet's supplied by platform feature. The latest version of this file for net9.0 can be seen [here](https://github.com/dotnet/runtime/blob/release/9.0/src/installer/pkg/sfx/Microsoft.NETCore.App/PackageOverrides.txt) and is included in the [targeting pack package](https://www.nuget.org/packages/Microsoft.NETCore.App.Ref). + +Once caclculating these we reduce them to a minimum set by allowing compatible frameworks to build upon the previous framework's data - thus reducing the total code size and memory usage of the set of framework packages. diff --git a/src/Microsoft.ComponentDetection.Detectors/nuget/NuGetPackageReferenceFrameworkAwareDetector.cs b/src/Microsoft.ComponentDetection.Detectors/nuget/NuGetPackageReferenceFrameworkAwareDetector.cs new file mode 100644 index 000000000..d661812ad --- /dev/null +++ b/src/Microsoft.ComponentDetection.Detectors/nuget/NuGetPackageReferenceFrameworkAwareDetector.cs @@ -0,0 +1,223 @@ +namespace Microsoft.ComponentDetection.Detectors.NuGet; + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using global::NuGet.Packaging.Core; +using global::NuGet.ProjectModel; +using global::NuGet.Versioning; +using Microsoft.ComponentDetection.Contracts; +using Microsoft.ComponentDetection.Contracts.Internal; +using Microsoft.ComponentDetection.Contracts.TypedComponent; +using Microsoft.Extensions.Logging; + +public class NuGetPackageReferenceFrameworkAwareDetector : FileComponentDetector, IExperimentalDetector +{ + public const string OmittedFrameworkComponentsTelemetryKey = "OmittedFrameworkComponents"; + + public const string ProjectDependencyType = "project"; + + private readonly IFileUtilityService fileUtilityService; + + public NuGetPackageReferenceFrameworkAwareDetector( + IComponentStreamEnumerableFactory componentStreamEnumerableFactory, + IObservableDirectoryWalkerFactory walkerFactory, + IFileUtilityService fileUtilityService, + ILogger logger) + { + this.ComponentStreamEnumerableFactory = componentStreamEnumerableFactory; + this.Scanner = walkerFactory; + this.fileUtilityService = fileUtilityService; + this.Logger = logger; + } + + public override string Id { get; } = "NuGetPackageReferenceFrameworkAware"; + + public override IEnumerable Categories => [Enum.GetName(typeof(DetectorClass), DetectorClass.NuGet)]; + + public override IList SearchPatterns { get; } = ["project.assets.json"]; + + public override IEnumerable SupportedComponentTypes { get; } = [ComponentType.NuGet]; + + public override int Version { get; } = 1; + + protected override Task OnFileFoundAsync(ProcessRequest processRequest, IDictionary detectorArgs, CancellationToken cancellationToken = default) + { + try + { + var lockFile = new LockFileFormat().Read(processRequest.ComponentStream.Stream, processRequest.ComponentStream.Location); + + this.RecordLockfileVersion(lockFile.Version); + + if (lockFile.PackageSpec == null) + { + throw new FormatException("Lockfile did not contain a PackageSpec"); + } + + var explicitReferencedDependencies = this.GetTopLevelLibraries(lockFile) + .Select(x => this.GetLibraryComponentWithDependencyLookup(lockFile.Libraries, x.Name, x.Version, x.VersionRange)) + .ToList(); + var explicitlyReferencedComponentIds = + explicitReferencedDependencies + .Select(x => new NuGetComponent(x.Name, x.Version.ToNormalizedString()).Id) + .ToHashSet(); + + // Since we report projects as the location, we ignore the passed in single file recorder. + var singleFileComponentRecorder = this.ComponentRecorder.CreateSingleFileComponentRecorder(lockFile.PackageSpec.RestoreMetadata.ProjectPath); + foreach (var target in lockFile.Targets) + { + var frameworkPackages = FrameworkPackages.GetFrameworkPackages(target.TargetFramework); + + // This call to GetTargetLibrary is not guarded, because if this can't be resolved then something is fundamentally broken (e.g. an explicit dependency reference not being in the list of libraries) + // issue: we treat top level dependencies for all targets as top level for each target, but some may not be top level for other targets, or may not even be present for other targets. + foreach (var library in explicitReferencedDependencies.Select(x => target.GetTargetLibrary(x.Name)).Where(x => x != null)) + { + this.NavigateAndRegister(target, explicitlyReferencedComponentIds, singleFileComponentRecorder, library, null, frameworkPackages); + } + } + } + catch (Exception e) + { + // If something went wrong, just ignore the package + this.Logger.LogError(e, "Failed to process NuGet lockfile {NuGetLockFile}", processRequest.ComponentStream.Location); + } + + return Task.CompletedTask; + } + + private void NavigateAndRegister( + LockFileTarget target, + HashSet explicitlyReferencedComponentIds, + ISingleFileComponentRecorder singleFileComponentRecorder, + LockFileTargetLibrary library, + string parentComponentId, + FrameworkPackages frameworkPackages, + HashSet visited = null) + { + if (library.Type == ProjectDependencyType) + { + return; + } + + var isFrameworkComponent = frameworkPackages?.IsAFrameworkComponent(library.Name, library.Version) ?? false; + var isDevelopmentDependency = IsADevelopmentDependency(library); + + visited ??= []; + + var libraryComponent = new DetectedComponent(new NuGetComponent(library.Name, library.Version.ToNormalizedString())); + singleFileComponentRecorder.RegisterUsage(libraryComponent, explicitlyReferencedComponentIds.Contains(libraryComponent.Component.Id), parentComponentId, isDevelopmentDependency: isFrameworkComponent || isDevelopmentDependency); + + // get the actual component in case it already exists + libraryComponent = singleFileComponentRecorder.GetComponent(libraryComponent.Component.Id); + + // Add framework information to the actual component + if (target.TargetFramework is not null) + { + ((NuGetComponent)libraryComponent.Component).TargetFrameworks.Add(target.TargetFramework.GetShortFolderName()); + } + + foreach (var dependency in library.Dependencies) + { + if (visited.Contains(dependency.Id)) + { + continue; + } + + var targetLibrary = target.GetTargetLibrary(dependency.Id); + if (targetLibrary == null) + { + // We have to exclude this case -- it looks like a bug in project.assets.json, but there are project.assets.json files that don't have a dependency library in the libraries set. + } + else + { + visited.Add(dependency.Id); + this.NavigateAndRegister(target, explicitlyReferencedComponentIds, singleFileComponentRecorder, targetLibrary, libraryComponent.Component.Id, frameworkPackages, visited); + } + } + + // a placeholder item is an empty file that doesn't exist with name _._ meant to indicate an empty folder in a nuget package, but also used by NuGet when a package's assets are excluded. + bool IsAPlaceholderItem(LockFileItem item) => Path.GetFileName(item.Path).Equals(PackagingCoreConstants.EmptyFolder, StringComparison.OrdinalIgnoreCase); + + // A library is development dependency if all of the runtime assemblies and runtime targets are placeholders or empty (All returns true for empty). + bool IsADevelopmentDependency(LockFileTargetLibrary library) => library.RuntimeAssemblies.Concat(library.RuntimeTargets).All(IsAPlaceholderItem); + } + + private List<(string Name, Version Version, VersionRange VersionRange)> GetTopLevelLibraries(LockFile lockFile) + { + // First, populate libraries from the TargetFrameworks section -- This is the base level authoritative list of nuget packages a project has dependencies on. + var toBeFilled = new List<(string Name, Version Version, VersionRange VersionRange)>(); + + foreach (var framework in lockFile.PackageSpec.TargetFrameworks) + { + foreach (var dependency in framework.Dependencies) + { + toBeFilled.Add((dependency.Name, Version: null, dependency.LibraryRange.VersionRange)); + } + } + + // Next, we need to resolve project references -- This is a little funky, because project references are only stored via path in + // project.assets.json, so we first build a list of all paths and then compare what is top level to them to resolve their + // associated library. + var projectDirectory = Path.GetDirectoryName(lockFile.PackageSpec.RestoreMetadata.ProjectPath); + var librariesWithAbsolutePath = + lockFile.Libraries.Where(x => x.Type == ProjectDependencyType) + .Select(x => (library: x, absoluteProjectPath: Path.GetFullPath(Path.Combine(projectDirectory, x.Path)))) + .ToDictionary(x => x.absoluteProjectPath, x => x.library); + + foreach (var restoreMetadataTargetFramework in lockFile.PackageSpec.RestoreMetadata.TargetFrameworks) + { + foreach (var projectReference in restoreMetadataTargetFramework.ProjectReferences) + { + if (librariesWithAbsolutePath.TryGetValue(Path.GetFullPath(projectReference.ProjectPath), out var library)) + { + toBeFilled.Add((library.Name, library.Version.Version, null)); + } + } + } + + return toBeFilled; + } + + // Looks up a library in project.assets.json given a version (preferred) or version range (have to in some cases due to how project.assets.json stores things) + private LockFileLibrary GetLibraryComponentWithDependencyLookup(IList libraries, string dependencyId, Version version, VersionRange versionRange) + { + if ((version == null && versionRange == null) || (version != null && versionRange != null)) + { + throw new ArgumentException($"Either {nameof(version)} or {nameof(versionRange)} must be specified, but not both."); + } + + var matchingLibraryNames = libraries.Where(x => string.Equals(x.Name, dependencyId, StringComparison.OrdinalIgnoreCase)).ToList(); + + if (matchingLibraryNames.Count == 0) + { + throw new InvalidOperationException("Project.assets.json is malformed, no library could be found matching: " + dependencyId); + } + + LockFileLibrary matchingLibrary; + if (version != null) + { + // .Version.Version ensures we get to a nuget normalized 4 part version + matchingLibrary = matchingLibraryNames.FirstOrDefault(x => x.Version.Version.Equals(version)); + } + else + { + matchingLibrary = matchingLibraryNames.FirstOrDefault(x => versionRange.Satisfies(x.Version)); + } + + if (matchingLibrary == null) + { + matchingLibrary = matchingLibraryNames.First(); + var versionString = versionRange != null ? versionRange.ToNormalizedString() : version.ToString(); + this.Logger.LogWarning( + "Couldn't satisfy lookup for {Version}. Falling back to first found component for {MatchingLibraryName}, resolving to version {MatchingLibraryVersion}.", + versionString, + matchingLibrary.Name, + matchingLibrary.Version); + } + + return matchingLibrary; + } +} diff --git a/src/Microsoft.ComponentDetection.Detectors/nuget/NuGetPackagesConfigDetector.cs b/src/Microsoft.ComponentDetection.Detectors/nuget/NuGetPackagesConfigDetector.cs index 44a899c27..c70c4b897 100644 --- a/src/Microsoft.ComponentDetection.Detectors/nuget/NuGetPackagesConfigDetector.cs +++ b/src/Microsoft.ComponentDetection.Detectors/nuget/NuGetPackagesConfigDetector.cs @@ -53,17 +53,32 @@ protected override Task OnFileFoundAsync(ProcessRequest processRequest, IDiction { try { + var singleFileComponentRecorder = processRequest.SingleFileComponentRecorder; var packagesConfig = new PackagesConfigReader(processRequest.ComponentStream.Stream); foreach (var package in packagesConfig.GetPackages(allowDuplicatePackageIds: true)) { - processRequest.SingleFileComponentRecorder.RegisterUsage( - new DetectedComponent( + var detectedComponent = new DetectedComponent( new NuGetComponent( package.PackageIdentity.Id, - package.PackageIdentity.Version.ToNormalizedString())), + package.PackageIdentity.Version.ToNormalizedString())); + + singleFileComponentRecorder.RegisterUsage( + detectedComponent, true, null, + /* TODO: Is this really the same concept? + Docs for NuGet say packages.config development dependencies are just not persisted as dependencies in the package. + That is not same as excluding from the output directory / runtime. */ package.IsDevelopmentDependency); + + // get the actual component in case it already exists + var libraryComponent = singleFileComponentRecorder.GetComponent(detectedComponent.Component.Id); + + // Add framework information to the actual component + if (package.TargetFramework is not null) + { + ((NuGetComponent)libraryComponent.Component).TargetFrameworks.Add(package.TargetFramework.GetShortFolderName()); + } } } catch (Exception e) when (e is PackagesConfigReaderException or XmlException) diff --git a/src/Microsoft.ComponentDetection.Detectors/nuget/NuGetProjectModelProjectCentricComponentDetector.cs b/src/Microsoft.ComponentDetection.Detectors/nuget/NuGetProjectModelProjectCentricComponentDetector.cs index 162f1b3d6..fd0b2e012 100644 --- a/src/Microsoft.ComponentDetection.Detectors/nuget/NuGetProjectModelProjectCentricComponentDetector.cs +++ b/src/Microsoft.ComponentDetection.Detectors/nuget/NuGetProjectModelProjectCentricComponentDetector.cs @@ -278,6 +278,15 @@ private void NavigateAndRegister( var libraryComponent = new DetectedComponent(new NuGetComponent(library.Name, library.Version.ToNormalizedString())); singleFileComponentRecorder.RegisterUsage(libraryComponent, explicitlyReferencedComponentIds.Contains(libraryComponent.Component.Id), parentComponentId); + // get the actual component in case it already exists + libraryComponent = singleFileComponentRecorder.GetComponent(libraryComponent.Component.Id); + + // Add framework information to the actual component + if (target.TargetFramework is not null) + { + ((NuGetComponent)libraryComponent.Component).TargetFrameworks.Add(target.TargetFramework.GetShortFolderName()); + } + foreach (var dependency in library.Dependencies) { if (visited.Contains(dependency.Id)) diff --git a/src/Microsoft.ComponentDetection.Orchestrator/Experiments/Configs/NuGetTargetFrameworkExperiment.cs b/src/Microsoft.ComponentDetection.Orchestrator/Experiments/Configs/NuGetTargetFrameworkExperiment.cs new file mode 100644 index 000000000..f3cf8b93c --- /dev/null +++ b/src/Microsoft.ComponentDetection.Orchestrator/Experiments/Configs/NuGetTargetFrameworkExperiment.cs @@ -0,0 +1,22 @@ +namespace Microsoft.ComponentDetection.Orchestrator.Experiments.Configs; + +using Microsoft.ComponentDetection.Contracts; +using Microsoft.ComponentDetection.Detectors.NuGet; + +/// +/// Validating the . +/// +public class NuGetTargetFrameworkExperiment : IExperimentConfiguration +{ + /// + public string Name => "NuGetTargetFrameworkAwareDetector"; + + /// + public bool IsInControlGroup(IComponentDetector componentDetector) => componentDetector is NuGetProjectModelProjectCentricComponentDetector; + + /// + public bool IsInExperimentGroup(IComponentDetector componentDetector) => componentDetector is NuGetPackageReferenceFrameworkAwareDetector; + + /// + public bool ShouldRecord(IComponentDetector componentDetector, int numComponents) => true; +} diff --git a/src/Microsoft.ComponentDetection.Orchestrator/Extensions/ServiceCollectionExtensions.cs b/src/Microsoft.ComponentDetection.Orchestrator/Extensions/ServiceCollectionExtensions.cs index 029ce096d..23f585a91 100644 --- a/src/Microsoft.ComponentDetection.Orchestrator/Extensions/ServiceCollectionExtensions.cs +++ b/src/Microsoft.ComponentDetection.Orchestrator/Extensions/ServiceCollectionExtensions.cs @@ -63,6 +63,7 @@ public static IServiceCollection AddComponentDetection(this IServiceCollection s services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); // Detectors // CocoaPods @@ -104,6 +105,7 @@ public static IServiceCollection AddComponentDetection(this IServiceCollection s services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); // PIP services.AddSingleton(); diff --git a/test/Microsoft.ComponentDetection.Detectors.Tests/nuget/NuGetPackageReferenceFrameworkAwareDetectorTests.cs b/test/Microsoft.ComponentDetection.Detectors.Tests/nuget/NuGetPackageReferenceFrameworkAwareDetectorTests.cs new file mode 100644 index 000000000..61c790c7c --- /dev/null +++ b/test/Microsoft.ComponentDetection.Detectors.Tests/nuget/NuGetPackageReferenceFrameworkAwareDetectorTests.cs @@ -0,0 +1,312 @@ +namespace Microsoft.ComponentDetection.Detectors.Tests; + +using System; +using System.Linq; +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using FluentAssertions; +using Microsoft.ComponentDetection.Contracts; +using Microsoft.ComponentDetection.Contracts.TypedComponent; +using Microsoft.ComponentDetection.Detectors.NuGet; +using Microsoft.ComponentDetection.Detectors.Tests.Mocks; +using Microsoft.ComponentDetection.Detectors.Tests.Utilities; +using Microsoft.ComponentDetection.TestsUtilities; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; + +[TestClass] +[TestCategory("Governance/All")] +[TestCategory("Governance/ComponentDetection")] +public class NuGetPackageReferenceFrameworkAwareDetectorTests : BaseDetectorTest +{ + private readonly string projectAssetsJsonFileName = "project.assets.json"; + private readonly Mock fileUtilityServiceMock; + + public NuGetPackageReferenceFrameworkAwareDetectorTests() + { + this.fileUtilityServiceMock = new Mock(); + this.fileUtilityServiceMock.Setup(x => x.Exists(It.IsAny())) + .Returns(true); + this.DetectorTestUtility.AddServiceMock(this.fileUtilityServiceMock); + } + + [TestMethod] + public async Task ScanDirectoryAsync_Base_2_2_VerificationAsync() + { + var osAgnostic = this.Convert22SampleToOSAgnostic(TestResources.project_assets_2_2); + var (scanResult, componentRecorder) = await this.DetectorTestUtility + .WithFile(this.projectAssetsJsonFileName, osAgnostic) + .ExecuteDetectorAsync(); + + var detectedComponents = componentRecorder.GetDetectedComponents(); + + // Number of unique nodes in ProjectAssetsJson + Console.WriteLine(string.Join(",", detectedComponents.Select(x => x.Component.Id))); + detectedComponents.Should().HaveCount(22); + + var nonDevComponents = detectedComponents.Where(c => !componentRecorder.GetEffectiveDevDependencyValue(c.Component.Id).GetValueOrDefault()); + nonDevComponents.Should().HaveCount(3); + + detectedComponents.Select(x => x.Component).Cast().FirstOrDefault(x => x.Name.Contains("coverlet.msbuild")).Should().NotBeNull(); + + componentRecorder.ForAllComponents(grouping => grouping.AllFileLocations.Should().Contain(location => location.Contains("Loader.csproj"))); + } + + [TestMethod] + public async Task ScanDirectoryAsync_Base_2_2_additional_VerificationAsync() + { + var osAgnostic = this.Convert22SampleToOSAgnostic(TestResources.project_assets_2_2_additional); + var (scanResult, componentRecorder) = await this.DetectorTestUtility + .WithFile(this.projectAssetsJsonFileName, osAgnostic) + .ExecuteDetectorAsync(); + + var detectedComponents = componentRecorder.GetDetectedComponents(); + + // Number of unique nodes in ProjectAssetsJson + Console.WriteLine(string.Join(",", detectedComponents.Select(x => x.Component.Id))); + detectedComponents.Should().HaveCount(68); + + var nonDevComponents = detectedComponents.Where(c => !componentRecorder.GetEffectiveDevDependencyValue(c.Component.Id).GetValueOrDefault()); + nonDevComponents.Should().HaveCount(23); + nonDevComponents.Select(x => x.Component).Cast().FirstOrDefault(x => x.Name.Contains("Polly")).Should().NotBeNull(); + nonDevComponents.Select(x => x.Component).Cast().Count(x => x.Name.Contains("System.Composition")).Should().Be(5); + + var nugetVersioning = nonDevComponents.FirstOrDefault(x => (x.Component as NuGetComponent).Name.Contains("NuGet.DependencyResolver.Core")); + nugetVersioning.Should().NotBeNull(); + + componentRecorder.IsDependencyOfExplicitlyReferencedComponents( + nugetVersioning.Component.Id, + x => x.Name.Contains("NuGet.ProjectModel")).Should().BeTrue(); + + componentRecorder.ForAllComponents(grouping => grouping.AllFileLocations.Should().Contain(location => location.Contains("Detectors.csproj"))); + } + + [TestMethod] + public async Task ScanDirectoryAsync_ExcludedFrameworkComponent_2_2_VerificationAsync() + { + var osAgnostic = this.Convert22SampleToOSAgnostic(TestResources.project_assets_2_2); + var (scanResult, componentRecorder) = await this.DetectorTestUtility + .WithFile(this.projectAssetsJsonFileName, osAgnostic) + .ExecuteDetectorAsync(); + + var developmentDependencies = componentRecorder.GetDetectedComponents().Where(c => componentRecorder.GetEffectiveDevDependencyValue(c.Component.Id).GetValueOrDefault()); + developmentDependencies.Should().HaveCountGreaterThan(5, "Ommitted framework assemblies are missing. There should be more than ten, but this is a gut check to make sure we have data."); + developmentDependencies.Should().Contain(c => c.Component.Id.StartsWith("Microsoft.NETCore.App "), "Microsoft.NETCore.App should be treated as a development dependency."); + } + + [TestMethod] + public async Task ScanDirectoryAsync_DependencyGraph_2_2_additional_VerificationAsync() + { + var osAgnostic = this.Convert22SampleToOSAgnostic(TestResources.project_assets_2_2_additional); + var (scanResult, componentRecorder) = await this.DetectorTestUtility + .WithFile(this.projectAssetsJsonFileName, osAgnostic) + .ExecuteDetectorAsync(); + var graphsByLocation = componentRecorder.GetDependencyGraphsByLocation(); + var graph = graphsByLocation.Values.First(); + + var expectedDependencyIdsForCompositionTypedParts = new[] + { + "NuGet.DependencyResolver.Core 5.6.0 - NuGet", + }; + + var detectedComponents = componentRecorder.GetDetectedComponents(); + var componentDetectionCommon = detectedComponents.First(x => x.Component.Id.Contains("NuGet.ProjectModel")); + var dependencies = graph.GetDependenciesForComponent(componentDetectionCommon.Component.Id); + foreach (var expectedId in expectedDependencyIdsForCompositionTypedParts) + { + dependencies.Should().Contain(expectedId); + } + + expectedDependencyIdsForCompositionTypedParts.Should().HaveSameCount(dependencies); + + detectedComponents.Should().HaveSameCount(graph.GetComponents()); + + // Top level dependencies look like this: + // (we expect all non-proj and non-framework to show up as explicit refs, so those will be absent from the check) + // + // "DotNet.Glob >= 2.1.1", + // "Microsoft.NETCore.App >= 2.2.8", + // "Microsoft.VisualStudio.Services.Governance.ComponentDetection.Common >= 1.0.0", + // "Microsoft.VisualStudio.Services.Governance.ComponentDetection.Contracts >= 1.0.0", + // "MinVer >= 2.5.0", + // "Nett >= 0.10.0", + // "Newtonsoft.Json >= 12.0.3", + // "NuGet.ProjectModel >= 5.6.0", + // "NuGet.Versioning >= 5.6.0", + // "Polly >= 7.0.3", + // "SemanticVersioning >= 1.2.0", + // "StyleCop.Analyzers >= 1.0.2", + // "System.Composition.AttributedModel >= 1.4.0", + // "System.Composition.Convention >= 1.4.0", + // "System.Composition.Hosting >= 1.4.0", + // "System.Composition.Runtime >= 1.4.0", + // "System.Composition.TypedParts >= 1.4.0", + // "System.Reactive >= 4.1.2", + // "System.Threading.Tasks.Dataflow >= 4.9.0", + // "coverlet.msbuild >= 2.5.1", + // "yamldotnet >= 5.3.0" + var expectedExplicitRefs = new[] + { + "DotNet.Glob", + "Microsoft.NETCore.App", + "MinVer", + "Nett", + "Newtonsoft.Json", + "NuGet.ProjectModel", + "NuGet.Versioning", + "Polly", + "SemanticVersioning", + "StyleCop.Analyzers", + "System.Composition.AttributedModel", + "System.Composition.Convention", + "System.Composition.Hosting", + "System.Composition.Runtime", + "System.Composition.TypedParts", + "System.Reactive", + "System.Threading.Tasks.Dataflow", + "coverlet.msbuild", + "YamlDotNet", + }; + + foreach (var componentId in graph.GetComponents()) + { + var component = detectedComponents.First(x => x.Component.Id == componentId); + var expectedExplicitRefValue = expectedExplicitRefs.Contains(((NuGetComponent)component.Component).Name); + graph.IsComponentExplicitlyReferenced(componentId).Should().Be(expectedExplicitRefValue, "{0} should{1} be explicitly referenced.", componentId, expectedExplicitRefValue ? string.Empty : "n't"); + } + } + + [TestMethod] + public async Task ScanDirectoryAsync_Base_3_1_VerificationAsync() + { + var osAgnostic = this.Convert31SampleToOSAgnostic(TestResources.project_assets_3_1); + var (scanResult, componentRecorder) = await this.DetectorTestUtility + .WithFile(this.projectAssetsJsonFileName, osAgnostic) + .ExecuteDetectorAsync(); + + // Number of unique nodes in ProjectAssetsJson + var detectedComponents = componentRecorder.GetDetectedComponents(); + detectedComponents.Should().HaveCount(11); + + var nonDevComponents = detectedComponents.Where(c => !componentRecorder.GetEffectiveDevDependencyValue(c.Component.Id).GetValueOrDefault()); + nonDevComponents.Should().ContainSingle(); + nonDevComponents.Select(x => x.Component).Cast().Single().Name.Should().StartWith("Microsoft.Extensions.DependencyModel"); + + var systemTextJson = detectedComponents.FirstOrDefault(x => (x.Component as NuGetComponent).Name.Contains("System.Text.Json")); + + componentRecorder.IsDependencyOfExplicitlyReferencedComponents( + systemTextJson.Component.Id, + x => x.Name.Contains("Microsoft.Extensions.DependencyModel")).Should().BeTrue(); + + componentRecorder.ForAllComponents(grouping => grouping.AllFileLocations.Should().Contain(location => location.Contains("ExtCore.WebApplication.csproj"))); + } + + [TestMethod] + public async Task ScanDirectoryAsync_ExcludedFrameworkComponent_3_1_VerificationAsync() + { + var osAgnostic = this.Convert31SampleToOSAgnostic(TestResources.project_assets_3_1); + var (scanResult, componentRecorder) = await this.DetectorTestUtility + .WithFile(this.projectAssetsJsonFileName, osAgnostic) + .ExecuteDetectorAsync(); + + var developmentDependencies = componentRecorder.GetDetectedComponents().Where(c => componentRecorder.GetEffectiveDevDependencyValue(c.Component.Id).GetValueOrDefault()); + developmentDependencies.Should().HaveCount(10, "Omitted framework assemblies are missing."); + developmentDependencies.Should().Contain(c => c.Component.Id.StartsWith("System.Reflection "), "System.Reflection should be treated as a development dependency."); + } + + [TestMethod] + public async Task ScanDirectoryAsync_DependencyGraph_3_1_VerificationAsync() + { + var osAgnostic = this.Convert31SampleToOSAgnostic(TestResources.project_assets_3_1); + var (scanResult, componentRecorder) = await this.DetectorTestUtility + .WithFile(this.projectAssetsJsonFileName, osAgnostic) + .ExecuteDetectorAsync(); + + var graphsByLocation = componentRecorder.GetDependencyGraphsByLocation(); + var graph = graphsByLocation.Values.First(); + + var expectedDependencyIdsForExtensionsDependencyModel = new[] + { + "System.Text.Json 4.6.0 - NuGet", + }; + + var detectedComponents = componentRecorder.GetDetectedComponents(); + + var componentDetectionCommon = detectedComponents.First(x => x.Component.Id.Contains("Microsoft.Extensions.DependencyModel")); + var dependencies = graph.GetDependenciesForComponent(componentDetectionCommon.Component.Id); + foreach (var expectedId in expectedDependencyIdsForExtensionsDependencyModel) + { + dependencies.Should().Contain(expectedId); + } + + detectedComponents.Should().HaveSameCount(graph.GetComponents()); + + // Top level dependencies look like this: + // (we expect all non-proj and non-framework to show up as explicit refs, so those will be absent from the check) + // + // "Microsoft.Extensions.DependencyModel >= 3.0.0", + // "System.Runtime.Loader >= 4.3.0" + var expectedExplicitRefs = new[] + { + "Microsoft.Extensions.DependencyModel", + "System.Runtime.Loader", + }; + + foreach (var componentId in graph.GetComponents()) + { + var component = detectedComponents.First(x => x.Component.Id == componentId); + var expectedExplicitRefValue = expectedExplicitRefs.Contains(((NuGetComponent)component.Component).Name); + graph.IsComponentExplicitlyReferenced(componentId).Should().Be(expectedExplicitRefValue, "{0} should{1} be explicitly referenced.", componentId, expectedExplicitRefValue ? string.Empty : "n't"); + } + } + + [TestMethod] + public async Task ScanDirectory_NoPackageSpecAsync() + { + var osAgnostic = + @"{ + ""version"": 3, + ""targets"": { + "".NETCoreApp,Version=v3.0"": {} + }, + ""packageFolders"": {} +}"; + var (scanResult, componentRecorder) = await this.DetectorTestUtility + .WithFile(this.projectAssetsJsonFileName, osAgnostic) + .ExecuteDetectorAsync(); + + scanResult.ResultCode.Should().Be(ProcessingResultCode.Success); + + var dependencyGraphs = componentRecorder.GetDependencyGraphsByLocation(); + + dependencyGraphs.Should().BeEmpty(); + } + + private string Convert22SampleToOSAgnostic(string project_assets) + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + return project_assets; + } + + project_assets = project_assets.Replace("D:\\\\Source\\\\componentdetection-bcde\\\\src\\\\Common\\\\", "/d/source/componentdetection-bcde/src/Common/"); + project_assets = project_assets.Replace("D:\\\\Source\\\\componentdetection-bcde\\\\src\\\\Contracts\\\\", "/d/source/componentdetection-bcde/src/Contracts/"); + project_assets = project_assets.Replace("D:\\\\Source\\\\componentdetection-bcde\\\\src\\\\Detectors\\\\", "/d/source/componentdetection-bcde/src/Detectors/"); + project_assets = project_assets.Replace("D:\\\\Source\\\\componentdetection-bcde\\\\src\\\\Orchestrator\\\\", "/d/source/componentdetection-bcde/src/Orchestrator/"); + project_assets = project_assets.Replace("D:\\\\Source\\\\componentdetection-bcde\\\\src\\\\Loader\\\\", "/d/source/componentdetection-bcde/src/Loader/"); + + return project_assets; + } + + private string Convert31SampleToOSAgnostic(string project_assets) + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + return project_assets; + } + + project_assets = project_assets.Replace("D:\\\\Source\\\\ExtCore\\\\src\\\\ExtCore.WebApplication\\\\", "/d/Source/ExtCore/src/ExtCore.WebApplication/"); + project_assets = project_assets.Replace("D:\\\\Source\\\\ExtCore\\\\src\\\\ExtCore.Infrastructure\\\\", "/d/Source/ExtCore/src/ExtCore.Infrastructure/"); + return project_assets; + } +} From a55475de45fc9e3ff79091ff2914b7ab8565b905 Mon Sep 17 00:00:00 2001 From: Greg Villicana <58237075+grvillic@users.noreply.github.com> Date: Sun, 3 Nov 2024 14:03:36 -0800 Subject: [PATCH 03/10] Report TargetFrameworks as part of DetectedComponent class (#1297) * Report TargetFrameworks as part of DetectedComponent class --- .../DependencyGraph/ComponentRecorder.cs | 9 ++- .../BcdeModels/ScannedComponent.cs | 2 + .../ConcurrentHashSet.cs | 63 +++++++++++++++++++ .../DetectedComponent.cs | 5 ++ .../IComponentRecorder.cs | 8 ++- .../TypedComponent/NugetComponent.cs | 3 - .../ivy/IvyDetector.cs | 2 +- ...tPackageReferenceFrameworkAwareDetector.cs | 24 +++---- .../nuget/NuGetPackagesConfigDetector.cs | 12 +--- ...ectModelProjectCentricComponentDetector.cs | 11 +--- .../DefaultGraphTranslationService.cs | 28 +++++++++ ...delProjectCentricComponentDetectorTests.cs | 10 +++ ...ageReferenceFrameworkAwareDetectorTests.cs | 14 +++-- .../nuget/NuGetPackagesConfigDetectorTests.cs | 18 ++++-- 14 files changed, 158 insertions(+), 51 deletions(-) create mode 100644 src/Microsoft.ComponentDetection.Contracts/ConcurrentHashSet.cs diff --git a/src/Microsoft.ComponentDetection.Common/DependencyGraph/ComponentRecorder.cs b/src/Microsoft.ComponentDetection.Common/DependencyGraph/ComponentRecorder.cs index 26e0b0111..7a9be52bf 100644 --- a/src/Microsoft.ComponentDetection.Common/DependencyGraph/ComponentRecorder.cs +++ b/src/Microsoft.ComponentDetection.Common/DependencyGraph/ComponentRecorder.cs @@ -160,7 +160,8 @@ public void RegisterUsage( bool isExplicitReferencedDependency = false, string parentComponentId = null, bool? isDevelopmentDependency = null, - DependencyScope? dependencyScope = null) + DependencyScope? dependencyScope = null, + string targetFramework = null) { ArgumentNullException.ThrowIfNull(detectedComponent); @@ -186,6 +187,12 @@ public void RegisterUsage( lock (this.registerUsageLock) { storedComponent = this.detectedComponentsInternal.GetOrAdd(componentId, detectedComponent); + + if (!string.IsNullOrWhiteSpace(targetFramework)) + { + storedComponent.TargetFrameworks.Add(targetFramework.Trim()); + } + this.AddComponentToGraph(this.ManifestFileLocation, detectedComponent, isExplicitReferencedDependency, parentComponentId, isDevelopmentDependency, dependencyScope); } } diff --git a/src/Microsoft.ComponentDetection.Contracts/BcdeModels/ScannedComponent.cs b/src/Microsoft.ComponentDetection.Contracts/BcdeModels/ScannedComponent.cs index 0a4463dff..f39649195 100644 --- a/src/Microsoft.ComponentDetection.Contracts/BcdeModels/ScannedComponent.cs +++ b/src/Microsoft.ComponentDetection.Contracts/BcdeModels/ScannedComponent.cs @@ -26,4 +26,6 @@ public class ScannedComponent public IEnumerable ContainerDetailIds { get; set; } public IDictionary> ContainerLayerIds { get; set; } + + public ISet TargetFrameworks { get; set; } } diff --git a/src/Microsoft.ComponentDetection.Contracts/ConcurrentHashSet.cs b/src/Microsoft.ComponentDetection.Contracts/ConcurrentHashSet.cs new file mode 100644 index 000000000..32dd55291 --- /dev/null +++ b/src/Microsoft.ComponentDetection.Contracts/ConcurrentHashSet.cs @@ -0,0 +1,63 @@ +namespace Microsoft.ComponentDetection.Contracts; + +using System.Collections; +using System.Collections.Concurrent; +using System.Collections.Generic; + +/// Represents a thread-safe set of values. +/// The type of elements in the hash set. +public class ConcurrentHashSet : IEnumerable +{ + private readonly ConcurrentDictionary dictionary; + + // Create different constructors for different equality comparers + public ConcurrentHashSet() => this.dictionary = new ConcurrentDictionary(); + + public ConcurrentHashSet(IEqualityComparer comparer) => this.dictionary = new ConcurrentDictionary(comparer); + + /// Adds the specific element to the object. + /// The element to add to the set. + /// true if element was added to object; false, if item was already present. + public bool Add(T item) + { + return this.dictionary.TryAdd(item, 0); + } + + /// Removes the specific element to the object. + /// The element to be removed from the set. + /// true if element was successfully found and removed; otherwise, false. + public bool Remove(T item) + { + return this.dictionary.TryRemove(item, out _); + } + + /// Determines whether the contains the specified element. + /// The element to locate in the object. + /// true if the object contains the specified element; otherwise, false. + public bool Contains(T item) + { + return this.dictionary.ContainsKey(item); + } + + /// Removes all elements from a object. + public void Clear() => this.dictionary.Clear(); + + public ISet ToHashSet() + { + return new HashSet(this.dictionary.Keys); + } + + /// Returns an enumerator that iterates through the . + /// An enumerator for the . + public IEnumerator GetEnumerator() + { + return this.dictionary.Keys.GetEnumerator(); + } + + /// Returns an enumerator that iterates through the . + /// An enumerator for the . + IEnumerator IEnumerable.GetEnumerator() + { + return this.GetEnumerator(); + } +} diff --git a/src/Microsoft.ComponentDetection.Contracts/DetectedComponent.cs b/src/Microsoft.ComponentDetection.Contracts/DetectedComponent.cs index eeefd6e10..e42043bb2 100644 --- a/src/Microsoft.ComponentDetection.Contracts/DetectedComponent.cs +++ b/src/Microsoft.ComponentDetection.Contracts/DetectedComponent.cs @@ -22,6 +22,8 @@ public DetectedComponent(TypedComponent.TypedComponent component, IComponentDete this.DetectedBy = detector; this.ContainerDetailIds = []; this.ContainerLayerIds = new Dictionary>(); + this.TargetFrameworks = []; + if (containerDetailsId.HasValue) { this.ContainerDetailIds.Add(containerDetailsId.Value); @@ -62,6 +64,9 @@ public DetectedComponent(TypedComponent.TypedComponent component, IComponentDete /// Gets or sets Dependency Scope of the component. public DependencyScope? DependencyScope { get; set; } + /// Gets Target Frameworks where the component was consumed. + public ConcurrentHashSet TargetFrameworks { get; set; } + private string DebuggerDisplay => $"{this.Component.DebuggerDisplay}"; /// Adds a filepath to the FilePaths hashset for this detected component. diff --git a/src/Microsoft.ComponentDetection.Contracts/IComponentRecorder.cs b/src/Microsoft.ComponentDetection.Contracts/IComponentRecorder.cs index f6ec737b5..dafaa23f1 100644 --- a/src/Microsoft.ComponentDetection.Contracts/IComponentRecorder.cs +++ b/src/Microsoft.ComponentDetection.Contracts/IComponentRecorder.cs @@ -23,20 +23,22 @@ public interface ISingleFileComponentRecorder IDependencyGraph DependencyGraph { get; } /// - /// Add or Update a component. In case that a parent componentId is specified - /// an edge is created between those components in the dependency graph. + /// Add or Update a component. In case that a parent componentId is specified an edge is created between those components in the dependency graph. + /// Metadata provided to this method specifies how the component was consumed, not uniquely identifying details about the component itself. /// /// Component to add. /// The value define if the component was referenced manually by the user in the location where the scanning is taking place. /// Id of the parent component. /// Boolean value indicating whether or not a component is a development-time dependency. Null implies that the value is unknown. /// Enum value indicating scope of the component. + /// Optional value to determine the framework where the component was consumed. void RegisterUsage( DetectedComponent detectedComponent, bool isExplicitReferencedDependency = false, string parentComponentId = null, bool? isDevelopmentDependency = null, - DependencyScope? dependencyScope = null); + DependencyScope? dependencyScope = null, + string targetFramework = null); /// /// Register that a package was unable to be processed. diff --git a/src/Microsoft.ComponentDetection.Contracts/TypedComponent/NugetComponent.cs b/src/Microsoft.ComponentDetection.Contracts/TypedComponent/NugetComponent.cs index c335d7fd4..dad787527 100644 --- a/src/Microsoft.ComponentDetection.Contracts/TypedComponent/NugetComponent.cs +++ b/src/Microsoft.ComponentDetection.Contracts/TypedComponent/NugetComponent.cs @@ -1,6 +1,5 @@ namespace Microsoft.ComponentDetection.Contracts.TypedComponent; -using System.Collections.Generic; using PackageUrl; public class NuGetComponent : TypedComponent @@ -23,8 +22,6 @@ public NuGetComponent(string name, string version, string[] authors = null) public string[] Authors { get; set; } - public ISet TargetFrameworks { get; set; } = new HashSet(); - public override ComponentType Type => ComponentType.NuGet; public override string Id => $"{this.Name} {this.Version} - {this.Type}"; diff --git a/src/Microsoft.ComponentDetection.Detectors/ivy/IvyDetector.cs b/src/Microsoft.ComponentDetection.Detectors/ivy/IvyDetector.cs index 0e9b8cb70..a18097927 100644 --- a/src/Microsoft.ComponentDetection.Detectors/ivy/IvyDetector.cs +++ b/src/Microsoft.ComponentDetection.Detectors/ivy/IvyDetector.cs @@ -35,7 +35,7 @@ namespace Microsoft.ComponentDetection.Detectors.Ivy; /// in the project's build.xml, or if they use any file inclusion mechanism, it will fail. /// /// The file written out by the custom Ant task is a simple JSON file representing a series of calls to be made to -/// the method. +/// the method. /// public class IvyDetector : FileComponentDetector, IExperimentalDetector { diff --git a/src/Microsoft.ComponentDetection.Detectors/nuget/NuGetPackageReferenceFrameworkAwareDetector.cs b/src/Microsoft.ComponentDetection.Detectors/nuget/NuGetPackageReferenceFrameworkAwareDetector.cs index d661812ad..a50bcc27c 100644 --- a/src/Microsoft.ComponentDetection.Detectors/nuget/NuGetPackageReferenceFrameworkAwareDetector.cs +++ b/src/Microsoft.ComponentDetection.Detectors/nuget/NuGetPackageReferenceFrameworkAwareDetector.cs @@ -108,16 +108,14 @@ private void NavigateAndRegister( visited ??= []; var libraryComponent = new DetectedComponent(new NuGetComponent(library.Name, library.Version.ToNormalizedString())); - singleFileComponentRecorder.RegisterUsage(libraryComponent, explicitlyReferencedComponentIds.Contains(libraryComponent.Component.Id), parentComponentId, isDevelopmentDependency: isFrameworkComponent || isDevelopmentDependency); - // get the actual component in case it already exists - libraryComponent = singleFileComponentRecorder.GetComponent(libraryComponent.Component.Id); - - // Add framework information to the actual component - if (target.TargetFramework is not null) - { - ((NuGetComponent)libraryComponent.Component).TargetFrameworks.Add(target.TargetFramework.GetShortFolderName()); - } + // Possibly adding target framework to single file recorder + singleFileComponentRecorder.RegisterUsage( + libraryComponent, + explicitlyReferencedComponentIds.Contains(libraryComponent.Component.Id), + parentComponentId, + isDevelopmentDependency: isFrameworkComponent || isDevelopmentDependency, + targetFramework: target.TargetFramework?.GetShortFolderName()); foreach (var dependency in library.Dependencies) { @@ -127,11 +125,9 @@ private void NavigateAndRegister( } var targetLibrary = target.GetTargetLibrary(dependency.Id); - if (targetLibrary == null) - { - // We have to exclude this case -- it looks like a bug in project.assets.json, but there are project.assets.json files that don't have a dependency library in the libraries set. - } - else + + // There are project.assets.json files that don't have a dependency library in the libraries set. + if (targetLibrary != null) { visited.Add(dependency.Id); this.NavigateAndRegister(target, explicitlyReferencedComponentIds, singleFileComponentRecorder, targetLibrary, libraryComponent.Component.Id, frameworkPackages, visited); diff --git a/src/Microsoft.ComponentDetection.Detectors/nuget/NuGetPackagesConfigDetector.cs b/src/Microsoft.ComponentDetection.Detectors/nuget/NuGetPackagesConfigDetector.cs index c70c4b897..ef7979304 100644 --- a/src/Microsoft.ComponentDetection.Detectors/nuget/NuGetPackagesConfigDetector.cs +++ b/src/Microsoft.ComponentDetection.Detectors/nuget/NuGetPackagesConfigDetector.cs @@ -66,19 +66,11 @@ protected override Task OnFileFoundAsync(ProcessRequest processRequest, IDiction detectedComponent, true, null, + targetFramework: package.TargetFramework?.GetShortFolderName(), /* TODO: Is this really the same concept? Docs for NuGet say packages.config development dependencies are just not persisted as dependencies in the package. That is not same as excluding from the output directory / runtime. */ - package.IsDevelopmentDependency); - - // get the actual component in case it already exists - var libraryComponent = singleFileComponentRecorder.GetComponent(detectedComponent.Component.Id); - - // Add framework information to the actual component - if (package.TargetFramework is not null) - { - ((NuGetComponent)libraryComponent.Component).TargetFrameworks.Add(package.TargetFramework.GetShortFolderName()); - } + isDevelopmentDependency: package.IsDevelopmentDependency); } } catch (Exception e) when (e is PackagesConfigReaderException or XmlException) diff --git a/src/Microsoft.ComponentDetection.Detectors/nuget/NuGetProjectModelProjectCentricComponentDetector.cs b/src/Microsoft.ComponentDetection.Detectors/nuget/NuGetProjectModelProjectCentricComponentDetector.cs index fd0b2e012..c5c38d6e3 100644 --- a/src/Microsoft.ComponentDetection.Detectors/nuget/NuGetProjectModelProjectCentricComponentDetector.cs +++ b/src/Microsoft.ComponentDetection.Detectors/nuget/NuGetProjectModelProjectCentricComponentDetector.cs @@ -276,16 +276,7 @@ private void NavigateAndRegister( visited ??= []; var libraryComponent = new DetectedComponent(new NuGetComponent(library.Name, library.Version.ToNormalizedString())); - singleFileComponentRecorder.RegisterUsage(libraryComponent, explicitlyReferencedComponentIds.Contains(libraryComponent.Component.Id), parentComponentId); - - // get the actual component in case it already exists - libraryComponent = singleFileComponentRecorder.GetComponent(libraryComponent.Component.Id); - - // Add framework information to the actual component - if (target.TargetFramework is not null) - { - ((NuGetComponent)libraryComponent.Component).TargetFrameworks.Add(target.TargetFramework.GetShortFolderName()); - } + singleFileComponentRecorder.RegisterUsage(libraryComponent, explicitlyReferencedComponentIds.Contains(libraryComponent.Component.Id), parentComponentId, targetFramework: target.TargetFramework?.GetShortFolderName()); foreach (var dependency in library.Dependencies) { diff --git a/src/Microsoft.ComponentDetection.Orchestrator/Services/GraphTranslation/DefaultGraphTranslationService.cs b/src/Microsoft.ComponentDetection.Orchestrator/Services/GraphTranslation/DefaultGraphTranslationService.cs index 07780b9d7..cb00860a4 100644 --- a/src/Microsoft.ComponentDetection.Orchestrator/Services/GraphTranslation/DefaultGraphTranslationService.cs +++ b/src/Microsoft.ComponentDetection.Orchestrator/Services/GraphTranslation/DefaultGraphTranslationService.cs @@ -46,6 +46,31 @@ public ScanResult GenerateScanResultFromProcessingResult( }; } + private static ConcurrentHashSet MergeTargetFrameworks(ConcurrentHashSet left, ConcurrentHashSet right) + { + if (left == null && right == null) + { + return []; + } + + if (left == null) + { + return right; + } + + if (right == null) + { + return left; + } + + foreach (var targetFramework in right) + { + left.Add(targetFramework); + } + + return left; + } + private void LogComponentScopeTelemetry(List components) { using var record = new DetectedComponentScopeRecord(); @@ -182,6 +207,8 @@ private DetectedComponent MergeComponents(IEnumerable enumera firstComponent.ContainerDetailIds.Add(containerDetailId); } } + + firstComponent.TargetFrameworks = MergeTargetFrameworks(firstComponent.TargetFrameworks, nextComponent.TargetFrameworks); } return firstComponent; @@ -271,6 +298,7 @@ private ScannedComponent ConvertToContract(DetectedComponent component) AncestralReferrers = component.AncestralDependencyRoots, ContainerDetailIds = component.ContainerDetailIds, ContainerLayerIds = component.ContainerLayerIds, + TargetFrameworks = component.TargetFrameworks?.ToHashSet(), }; } } diff --git a/test/Microsoft.ComponentDetection.Detectors.Tests/NuGetProjectModelProjectCentricComponentDetectorTests.cs b/test/Microsoft.ComponentDetection.Detectors.Tests/NuGetProjectModelProjectCentricComponentDetectorTests.cs index 04ce211f2..ee2bb7048 100644 --- a/test/Microsoft.ComponentDetection.Detectors.Tests/NuGetProjectModelProjectCentricComponentDetectorTests.cs +++ b/test/Microsoft.ComponentDetection.Detectors.Tests/NuGetProjectModelProjectCentricComponentDetectorTests.cs @@ -52,6 +52,11 @@ public async Task ScanDirectoryAsync_Base_2_2_VerificationAsync() x.Component.Id, y => y.Id == x.Component.Id)); + foreach (var component in detectedComponents) + { + component.TargetFrameworks.Should().BeEquivalentTo(["netcoreapp2.2"]); + } + componentRecorder.ForAllComponents(grouping => grouping.AllFileLocations.Should().Contain(location => location.Contains("Loader.csproj"))); } @@ -195,6 +200,11 @@ public async Task ScanDirectoryAsync_Base_3_1_VerificationAsync() systemTextJson.Component.Id, x => x.Name.Contains("Microsoft.Extensions.DependencyModel")).Should().BeTrue(); + foreach (var component in detectedComponents) + { + component.TargetFrameworks.Should().BeEquivalentTo(["netcoreapp3.1"]); + } + componentRecorder.ForAllComponents(grouping => grouping.AllFileLocations.Should().Contain(location => location.Contains("ExtCore.WebApplication.csproj"))); } diff --git a/test/Microsoft.ComponentDetection.Detectors.Tests/nuget/NuGetPackageReferenceFrameworkAwareDetectorTests.cs b/test/Microsoft.ComponentDetection.Detectors.Tests/nuget/NuGetPackageReferenceFrameworkAwareDetectorTests.cs index 61c790c7c..da2712c0a 100644 --- a/test/Microsoft.ComponentDetection.Detectors.Tests/nuget/NuGetPackageReferenceFrameworkAwareDetectorTests.cs +++ b/test/Microsoft.ComponentDetection.Detectors.Tests/nuget/NuGetPackageReferenceFrameworkAwareDetectorTests.cs @@ -40,13 +40,16 @@ public async Task ScanDirectoryAsync_Base_2_2_VerificationAsync() var detectedComponents = componentRecorder.GetDetectedComponents(); - // Number of unique nodes in ProjectAssetsJson - Console.WriteLine(string.Join(",", detectedComponents.Select(x => x.Component.Id))); detectedComponents.Should().HaveCount(22); var nonDevComponents = detectedComponents.Where(c => !componentRecorder.GetEffectiveDevDependencyValue(c.Component.Id).GetValueOrDefault()); nonDevComponents.Should().HaveCount(3); + foreach (var component in detectedComponents) + { + component.TargetFrameworks.Should().BeEquivalentTo(["netcoreapp2.2"]); + } + detectedComponents.Select(x => x.Component).Cast().FirstOrDefault(x => x.Name.Contains("coverlet.msbuild")).Should().NotBeNull(); componentRecorder.ForAllComponents(grouping => grouping.AllFileLocations.Should().Contain(location => location.Contains("Loader.csproj"))); @@ -62,8 +65,6 @@ public async Task ScanDirectoryAsync_Base_2_2_additional_VerificationAsync() var detectedComponents = componentRecorder.GetDetectedComponents(); - // Number of unique nodes in ProjectAssetsJson - Console.WriteLine(string.Join(",", detectedComponents.Select(x => x.Component.Id))); detectedComponents.Should().HaveCount(68); var nonDevComponents = detectedComponents.Where(c => !componentRecorder.GetEffectiveDevDependencyValue(c.Component.Id).GetValueOrDefault()); @@ -198,6 +199,11 @@ public async Task ScanDirectoryAsync_Base_3_1_VerificationAsync() systemTextJson.Component.Id, x => x.Name.Contains("Microsoft.Extensions.DependencyModel")).Should().BeTrue(); + foreach (var component in detectedComponents) + { + component.TargetFrameworks.Should().BeEquivalentTo(["netcoreapp3.1"]); + } + componentRecorder.ForAllComponents(grouping => grouping.AllFileLocations.Should().Contain(location => location.Contains("ExtCore.WebApplication.csproj"))); } diff --git a/test/Microsoft.ComponentDetection.Detectors.Tests/nuget/NuGetPackagesConfigDetectorTests.cs b/test/Microsoft.ComponentDetection.Detectors.Tests/nuget/NuGetPackagesConfigDetectorTests.cs index f492ede7e..29281a1cb 100644 --- a/test/Microsoft.ComponentDetection.Detectors.Tests/nuget/NuGetPackagesConfigDetectorTests.cs +++ b/test/Microsoft.ComponentDetection.Detectors.Tests/nuget/NuGetPackagesConfigDetectorTests.cs @@ -14,11 +14,12 @@ public class NuGetPackagesConfigDetectorTests : BaseDetectorTest + @$" - - + + "; var (scanResult, componentRecorder) = await this.DetectorTestUtility @@ -27,10 +28,17 @@ public async Task Should_WorkAsync() scanResult.ResultCode.Should().Be(ProcessingResultCode.Success); var detectedComponents = componentRecorder.GetDetectedComponents(); + + var jqueryDetectedComponent = new DetectedComponent(new NuGetComponent("jQuery", "3.1.1")); + jqueryDetectedComponent.TargetFrameworks.Add(targetFramework); + + var nlogDetectedComponent = new DetectedComponent(new NuGetComponent("NLog", "4.3.10")); + nlogDetectedComponent.TargetFrameworks.Add(targetFramework); + detectedComponents.Should().NotBeEmpty() .And.HaveCount(2) - .And.ContainEquivalentOf(new DetectedComponent(new NuGetComponent("jQuery", "3.1.1"))) - .And.ContainEquivalentOf(new DetectedComponent(new NuGetComponent("NLog", "4.3.10"))); + .And.ContainEquivalentOf(jqueryDetectedComponent) + .And.ContainEquivalentOf(nlogDetectedComponent); } [TestMethod] From 60c6b90a5d8e9d794ea7f2ddf75ef7378f855a5a Mon Sep 17 00:00:00 2001 From: Eric StJohn Date: Thu, 14 Nov 2024 12:29:45 -0800 Subject: [PATCH 04/10] Record NuGet PackageDownloads (#1296) * Record NuGet PackageDownloads Read PackageDownloads from the assets file and record them as top-level development dependencies. --- ...tPackageReferenceFrameworkAwareDetector.cs | 27 +++++ .../Mocks/TestResources.Designer.cs | 59 +++++++--- .../Mocks/TestResources.resx | 3 + .../project_assets_packageDownload.json | 106 ++++++++++++++++++ ...ageReferenceFrameworkAwareDetectorTests.cs | 13 +++ 5 files changed, 192 insertions(+), 16 deletions(-) create mode 100644 test/Microsoft.ComponentDetection.Detectors.Tests/Resources/project_assets_packageDownload.json diff --git a/src/Microsoft.ComponentDetection.Detectors/nuget/NuGetPackageReferenceFrameworkAwareDetector.cs b/src/Microsoft.ComponentDetection.Detectors/nuget/NuGetPackageReferenceFrameworkAwareDetector.cs index a50bcc27c..628d997f9 100644 --- a/src/Microsoft.ComponentDetection.Detectors/nuget/NuGetPackageReferenceFrameworkAwareDetector.cs +++ b/src/Microsoft.ComponentDetection.Detectors/nuget/NuGetPackageReferenceFrameworkAwareDetector.cs @@ -78,6 +78,9 @@ protected override Task OnFileFoundAsync(ProcessRequest processRequest, IDiction this.NavigateAndRegister(target, explicitlyReferencedComponentIds, singleFileComponentRecorder, library, null, frameworkPackages); } } + + // Register PackageDownload + this.RegisterPackageDownloads(singleFileComponentRecorder, lockFile); } catch (Exception e) { @@ -141,6 +144,30 @@ private void NavigateAndRegister( bool IsADevelopmentDependency(LockFileTargetLibrary library) => library.RuntimeAssemblies.Concat(library.RuntimeTargets).All(IsAPlaceholderItem); } + private void RegisterPackageDownloads(ISingleFileComponentRecorder singleFileComponentRecorder, LockFile lockFile) + { + foreach (var framework in lockFile.PackageSpec.TargetFrameworks) + { + foreach (var packageDownload in framework.DownloadDependencies) + { + if (packageDownload?.Name is null || packageDownload?.VersionRange?.MinVersion is null) + { + continue; + } + + var libraryComponent = new DetectedComponent(new NuGetComponent(packageDownload.Name, packageDownload.VersionRange.MinVersion.ToNormalizedString())); + + // PackageDownload is always a development dependency since it's usage does not make it part of the application + singleFileComponentRecorder.RegisterUsage( + libraryComponent, + isExplicitReferencedDependency: true, + parentComponentId: null, + isDevelopmentDependency: true, + targetFramework: framework.FrameworkName?.GetShortFolderName()); + } + } + } + private List<(string Name, Version Version, VersionRange VersionRange)> GetTopLevelLibraries(LockFile lockFile) { // First, populate libraries from the TargetFrameworks section -- This is the base level authoritative list of nuget packages a project has dependencies on. diff --git a/test/Microsoft.ComponentDetection.Detectors.Tests/Mocks/TestResources.Designer.cs b/test/Microsoft.ComponentDetection.Detectors.Tests/Mocks/TestResources.Designer.cs index d0db6536e..38496cb38 100644 --- a/test/Microsoft.ComponentDetection.Detectors.Tests/Mocks/TestResources.Designer.cs +++ b/test/Microsoft.ComponentDetection.Detectors.Tests/Mocks/TestResources.Designer.cs @@ -10,8 +10,8 @@ namespace Microsoft.ComponentDetection.Detectors.Tests.Mocks { using System; - - + + /// /// A strongly-typed resource class, for looking up localized strings, etc. /// @@ -23,15 +23,15 @@ namespace Microsoft.ComponentDetection.Detectors.Tests.Mocks { [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class TestResources { - + private static global::System.Resources.ResourceManager resourceMan; - + private static global::System.Globalization.CultureInfo resourceCulture; - + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal TestResources() { } - + /// /// Returns the cached ResourceManager instance used by this class. /// @@ -45,7 +45,7 @@ internal TestResources() { return resourceMan; } } - + /// /// Overrides the current thread's CurrentUICulture property for all /// resource lookups using this strongly typed resource class. @@ -59,7 +59,7 @@ internal TestResources() { resourceCulture = value; } } - + /// /// Looks up a localized string similar to integrationTestCompileClasspath - Compile classpath for source set 'integration test'. ///+--- commons-io:commons-io:2.5 @@ -77,7 +77,7 @@ internal static string GradlewDependencyOutput { return ResourceManager.GetString("GradlewDependencyOutput", resourceCulture); } } - + /// /// Looks up a localized string similar to org.apache.maven:maven-compat:jar:3.6.1-SNAPSHOT ///+- org.apache.maven:maven-model:jar:3.6.1-SNAPSHOT:compile @@ -94,7 +94,7 @@ internal static string MvnCliDependencyOutput { return ResourceManager.GetString("MvnCliDependencyOutput", resourceCulture); } } - + /// /// Looks up a localized string similar to { /// "version": "1", @@ -115,7 +115,7 @@ internal static string pip_report_jupyterlab { return ResourceManager.GetString("pip_report_jupyterlab", resourceCulture); } } - + /// /// Looks up a localized string similar to { /// "version": "1", @@ -137,7 +137,7 @@ internal static string pip_report_multi_pkg { return ResourceManager.GetString("pip_report_multi_pkg", resourceCulture); } } - + /// /// Looks up a localized string similar to { /// "version": "1", @@ -158,7 +158,7 @@ internal static string pip_report_simple_extras { return ResourceManager.GetString("pip_report_simple_extras", resourceCulture); } } - + /// /// Looks up a localized string similar to { /// "version": "1", @@ -180,7 +180,7 @@ internal static string pip_report_single_pkg { return ResourceManager.GetString("pip_report_single_pkg", resourceCulture); } } - + /// /// Looks up a localized string similar to { /// "version": "2", @@ -256,7 +256,7 @@ internal static string project_assets_2_2 { return ResourceManager.GetString("project_assets_2_2", resourceCulture); } } - + /// /// Looks up a localized string similar to { /// "version": 3, @@ -286,7 +286,7 @@ internal static string project_assets_2_2_additional { return ResourceManager.GetString("project_assets_2_2_additional", resourceCulture); } } - + /// /// Looks up a localized string similar to { /// "version": 3, @@ -311,5 +311,32 @@ internal static string project_assets_3_1 { return ResourceManager.GetString("project_assets_3_1", resourceCulture); } } + + /// + /// Looks up a localized string similar to { + /// "version": 3, + /// "targets": { + /// ".NETFramework,Version=v4.7.2": {}, + /// "net8.0": {} + /// }, + /// "libraries": {}, + /// "projectFileDependencyGroups": { + /// ".NETFramework,Version=v4.7.2": [], + /// "net8.0": [] + /// }, + /// "packageFolders": { + /// "C:\\Users\\username\\.nuget\\packages\\": {}, + /// "C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages": {} + /// }, + /// "project": { + /// "version": "1.0.0", + /// "restore": { + /// "projectUniqueName": "C:\\src\\packageDownloadSample\\package [rest of string was truncated]";. + /// + internal static string project_assets_packageDownload { + get { + return ResourceManager.GetString("project_assets_packageDownload", resourceCulture); + } + } } } diff --git a/test/Microsoft.ComponentDetection.Detectors.Tests/Mocks/TestResources.resx b/test/Microsoft.ComponentDetection.Detectors.Tests/Mocks/TestResources.resx index 9bb9bca31..2fda73e51 100644 --- a/test/Microsoft.ComponentDetection.Detectors.Tests/Mocks/TestResources.resx +++ b/test/Microsoft.ComponentDetection.Detectors.Tests/Mocks/TestResources.resx @@ -151,4 +151,7 @@ ..\Resources\project_assets_3_1.json;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252 + + ..\Resources\project_assets_packageDownload.json;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252 + \ No newline at end of file diff --git a/test/Microsoft.ComponentDetection.Detectors.Tests/Resources/project_assets_packageDownload.json b/test/Microsoft.ComponentDetection.Detectors.Tests/Resources/project_assets_packageDownload.json new file mode 100644 index 000000000..44a5959d8 --- /dev/null +++ b/test/Microsoft.ComponentDetection.Detectors.Tests/Resources/project_assets_packageDownload.json @@ -0,0 +1,106 @@ +{ + "version": 3, + "targets": { + ".NETFramework,Version=v4.7.2": {}, + "net8.0": {} + }, + "libraries": {}, + "projectFileDependencyGroups": { + ".NETFramework,Version=v4.7.2": [], + "net8.0": [] + }, + "packageFolders": { + "C:\\Users\\username\\.nuget\\packages\\": {}, + "C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages": {} + }, + "project": { + "version": "1.0.0", + "restore": { + "projectUniqueName": "C:\\src\\packageDownloadSample\\packageDownloadSample.csproj", + "projectName": "packageDownloadSample", + "projectPath": "C:\\src\\packageDownloadSample\\packageDownloadSample.csproj", + "packagesPath": "C:\\Users\\username\\.nuget\\packages\\", + "outputPath": "C:\\src\\packageDownloadSample\\obj\\", + "projectStyle": "PackageReference", + "crossTargeting": true, + "fallbackFolders": [ + "C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages" + ], + "configFilePaths": [ + "C:\\Users\\username\\AppData\\Roaming\\NuGet\\NuGet.Config", + "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config", + "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config" + ], + "originalTargetFrameworks": [ + "net472", + "net8.0" + ], + "sources": { + "C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {}, + "C:\\Program Files\\dotnet\\library-packs": {}, + "https://api.nuget.org/v3/index.json": {} + }, + "frameworks": { + "net8.0": { + "targetAlias": "net8.0", + "projectReferences": {} + }, + "net472": { + "targetAlias": "net472", + "projectReferences": {} + } + }, + "warningProperties": { + "warnAsError": [ + "NU1605" + ] + }, + "restoreAuditProperties": { + "enableAudit": "true", + "auditLevel": "low", + "auditMode": "all" + }, + "SdkAnalysisLevel": "9.0.100" + }, + "frameworks": { + "net8.0": { + "targetAlias": "net8.0", + "imports": [ + "net461", + "net462", + "net47", + "net471", + "net472", + "net48", + "net481" + ], + "assetTargetFallback": true, + "warn": true, + "downloadDependencies": [ + { + "name": "Microsoft.Build", + "version": "[17.8.3, 17.8.3]" + }, + { + "name": "Microsoft.Build.Framework", + "version": "[17.8.3, 17.8.3]" + }, + { + "name": "Microsoft.Build.Utilities.Core", + "version": "[17.8.3, 17.8.3]" + } + ], + "frameworkReferences": { + "Microsoft.NETCore.App": { + "privateAssets": "all" + } + }, + "runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\9.0.100/PortableRuntimeIdentifierGraph.json" + }, + "net472": { + "targetAlias": "net472", + "runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\9.0.100\\RuntimeIdentifierGraph.json" + } + } + } +} diff --git a/test/Microsoft.ComponentDetection.Detectors.Tests/nuget/NuGetPackageReferenceFrameworkAwareDetectorTests.cs b/test/Microsoft.ComponentDetection.Detectors.Tests/nuget/NuGetPackageReferenceFrameworkAwareDetectorTests.cs index da2712c0a..922509b37 100644 --- a/test/Microsoft.ComponentDetection.Detectors.Tests/nuget/NuGetPackageReferenceFrameworkAwareDetectorTests.cs +++ b/test/Microsoft.ComponentDetection.Detectors.Tests/nuget/NuGetPackageReferenceFrameworkAwareDetectorTests.cs @@ -266,6 +266,19 @@ public async Task ScanDirectoryAsync_DependencyGraph_3_1_VerificationAsync() } } + [TestMethod] + public async Task ScanDirectoryAsync_PackageDownload_VerificationAsync() + { + var (scanResult, componentRecorder) = await this.DetectorTestUtility + .WithFile(this.projectAssetsJsonFileName, TestResources.project_assets_packageDownload) + .ExecuteDetectorAsync(); + + var developmentDependencies = componentRecorder.GetDetectedComponents().Where(c => componentRecorder.GetEffectiveDevDependencyValue(c.Component.Id).GetValueOrDefault()); + developmentDependencies.Should().HaveCount(3, "PackageDownload dev dependencies should exist."); + developmentDependencies.Select(c => c.Component).Should().AllBeOfType(); + developmentDependencies.Select(c => c.TargetFrameworks).Should().AllSatisfy(tfms => tfms.Should().BeEquivalentTo(["net8.0"])); + } + [TestMethod] public async Task ScanDirectory_NoPackageSpecAsync() { From 9408a0e5111759718d236dd86dd5b8e2d0e6cb3a Mon Sep 17 00:00:00 2001 From: Eric StJohn Date: Thu, 14 Nov 2024 14:18:35 -0800 Subject: [PATCH 05/10] Detect nuget framework packages for additional frameworks (#1300) * Detect nuget framework packages for additional frameworks This adds support for additional framework references - Microsoft.AspNetCore.App and Microsoft.WindowsDesktop.App --- .../FrameworkPackages/FrameworkPackages.cs | 163 ++-- .../FrameworkPackages.net5.0.cs | 228 +++-- .../FrameworkPackages.net6.0.cs | 177 +++- .../FrameworkPackages.net7.0.cs | 164 +++- .../FrameworkPackages.net8.0.cs | 174 +++- .../FrameworkPackages.net9.0.cs | 222 +++-- .../FrameworkPackages.netcoreapp2.0.cs | 166 +++- .../FrameworkPackages.netcoreapp2.1.cs | 19 +- .../FrameworkPackages.netcoreapp2.2.cs | 6 +- .../FrameworkPackages.netcoreapp3.0.cs | 192 ++++- .../FrameworkPackages.netcoreapp3.1.cs | 171 +++- .../FrameworkPackages.netstandard2.0.cs | 6 +- .../FrameworkPackages.netstandard2.1.cs | 6 +- ...tPackageReferenceFrameworkAwareDetector.cs | 30 +- .../Mocks/TestResources.Designer.cs | 782 ++++++++++-------- .../Mocks/TestResources.resx | 18 +- .../Resources/project_assets_42_15_web.json | 437 ++++++++++ ...roject_assets_6_0_8_0_multi_framework.json | 321 +++++++ .../project_assets_8_0_multi_framework.json | 226 +++++ .../Resources/project_assets_8_0_web.json | 460 +++++++++++ ...ageReferenceFrameworkAwareDetectorTests.cs | 55 +- 21 files changed, 3447 insertions(+), 576 deletions(-) create mode 100644 test/Microsoft.ComponentDetection.Detectors.Tests/Resources/project_assets_42_15_web.json create mode 100644 test/Microsoft.ComponentDetection.Detectors.Tests/Resources/project_assets_6_0_8_0_multi_framework.json create mode 100644 test/Microsoft.ComponentDetection.Detectors.Tests/Resources/project_assets_8_0_multi_framework.json create mode 100644 test/Microsoft.ComponentDetection.Detectors.Tests/Resources/project_assets_8_0_web.json diff --git a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.cs b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.cs index b6a9c5da1..cae44ea35 100644 --- a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.cs +++ b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.cs @@ -2,6 +2,7 @@ namespace Microsoft.ComponentDetection.Detectors.NuGet; using System; using System.Collections; +using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; @@ -15,91 +16,139 @@ namespace Microsoft.ComponentDetection.Detectors.NuGet; /// internal sealed partial class FrameworkPackages : IEnumerable>, IEnumerable { - private static readonly Dictionary FrameworkPackagesByFramework = []; + private const string DefaultFrameworkKey = ""; + private static readonly ConcurrentDictionary> FrameworkPackagesByFramework = []; static FrameworkPackages() { - AddPackages(NETStandard20.Instance); - AddPackages(NETStandard21.Instance); - AddPackages(NETCoreApp20.Instance); - AddPackages(NETCoreApp21.Instance); - AddPackages(NETCoreApp22.Instance); - AddPackages(NETCoreApp30.Instance); - AddPackages(NETCoreApp31.Instance); - AddPackages(NETCoreApp50.Instance); - AddPackages(NETCoreApp60.Instance); - AddPackages(NETCoreApp70.Instance); - AddPackages(NETCoreApp80.Instance); - AddPackages(NETCoreApp90.Instance); - - static void AddPackages(FrameworkPackages packages) => FrameworkPackagesByFramework[packages.Framework] = packages; + NETStandard20.Register(); + NETStandard21.Register(); + NETCoreApp20.Register(); + NETCoreApp21.Register(); + NETCoreApp22.Register(); + NETCoreApp30.Register(); + NETCoreApp31.Register(); + NETCoreApp50.Register(); + NETCoreApp60.Register(); + NETCoreApp70.Register(); + NETCoreApp80.Register(); + NETCoreApp90.Register(); } - public FrameworkPackages(NuGetFramework framework) => this.Framework = framework; + public FrameworkPackages(NuGetFramework framework, string frameworkName) + { + this.Framework = framework; + this.FrameworkName = frameworkName; + } - public FrameworkPackages(NuGetFramework framework, FrameworkPackages frameworkPackages) - : this(framework) => this.Packages = new(frameworkPackages.Packages); + public FrameworkPackages(NuGetFramework framework, string frameworkName, FrameworkPackages frameworkPackages) + : this(framework, frameworkName) => this.Packages = new(frameworkPackages.Packages); public NuGetFramework Framework { get; } + public string FrameworkName { get; } + public Dictionary Packages { get; } = new Dictionary(StringComparer.OrdinalIgnoreCase); - public static FrameworkPackages GetFrameworkPackages(NuGetFramework framework) - { - if (FrameworkPackagesByFramework.TryGetValue(framework, out var frameworkPackages)) + private static string GetFrameworkKey(string frameworkName) => + frameworkName switch { - return frameworkPackages; - } + FrameworkNames.NetStandardLibrary => DefaultFrameworkKey, + FrameworkNames.NetCoreApp => DefaultFrameworkKey, + _ => frameworkName, + }; - // if we didn't predefine the package overrides, load them from the targeting pack - // we might just leave this out since in future frameworks we'll have this functionality built into NuGet. - var frameworkPackagesFromPack = LoadFrameworkPackagesFromPack(framework); + internal static void Register(params FrameworkPackages[] toRegister) + { + foreach (var frameworkPackages in toRegister) + { + if (!FrameworkPackagesByFramework.TryGetValue(frameworkPackages.Framework, out var frameworkPackagesForVersion)) + { + FrameworkPackagesByFramework[frameworkPackages.Framework] = frameworkPackagesForVersion = []; + } - return FrameworkPackagesByFramework[framework] = frameworkPackagesFromPack ?? new FrameworkPackages(framework); + var frameworkKey = GetFrameworkKey(frameworkPackages.FrameworkName); + frameworkPackagesForVersion[frameworkKey] = frameworkPackages; + } } - private static FrameworkPackages LoadFrameworkPackagesFromPack(NuGetFramework framework) + public static FrameworkPackages[] GetFrameworkPackages(NuGetFramework framework, string[] frameworkReferences) { - if (framework is null || framework.Framework != FrameworkConstants.FrameworkIdentifiers.NetCoreApp) + var frameworkPackages = new List(); + + if (frameworkReferences.Length == 0) { - return null; + frameworkReferences = [DefaultFrameworkKey]; } - // packs location : %ProgramFiles%\dotnet\packs - var packsFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "dotnet", "packs", "Microsoft.NETCore.App.Ref"); - if (!Directory.Exists(packsFolder)) + foreach (var frameworkReference in frameworkReferences) { - return null; + var frameworkKey = GetFrameworkKey(frameworkReference); + if (FrameworkPackagesByFramework.TryGetValue(framework, out var frameworkPackagesForVersion) && + frameworkPackagesForVersion.TryGetValue(frameworkKey, out var frameworkPackage)) + { + frameworkPackages.Add(frameworkPackage); + } + else + { + // if we didn't predefine the package overrides, load them from the targeting pack + // we might just leave this out since in future frameworks we'll have this functionality built into NuGet.Frameworks + var frameworkPackagesFromPack = LoadFrameworkPackagesFromPack(framework, frameworkReference) ?? new FrameworkPackages(framework, frameworkReference); + + Register(frameworkPackagesFromPack); + + frameworkPackages.Add(frameworkPackagesFromPack); + } } - var packVersionPattern = $"{framework.Version.Major}.{framework.Version.Minor}.*"; - var packDirectories = Directory.GetDirectories(packsFolder, packVersionPattern); - var packageOverridesFile = packDirectories - .Select(d => (Overrides: Path.Combine(d, "data", "PackageOverrides.txt"), Version: ParseVersion(Path.GetFileName(d)))) - .Where(d => File.Exists(d.Overrides)) - .OrderByDescending(d => d.Version) - .FirstOrDefault().Overrides; + return frameworkPackages.ToArray(); + } - if (packageOverridesFile == null) + private static FrameworkPackages LoadFrameworkPackagesFromPack(NuGetFramework framework, string frameworkName) + { + if (framework is null || framework.Framework != FrameworkConstants.FrameworkIdentifiers.NetCoreApp) { - // we should also try to grab them from the user's package folder - they'll be in one location or the other. return null; } - // Adapted from https://github.com/dotnet/sdk/blob/c3a8f72c3a5491c693ff8e49e7406136a12c3040/src/Tasks/Common/ConflictResolution/PackageOverride.cs#L52-L68 - var frameworkPackages = new FrameworkPackages(framework); - var packageOverrides = File.ReadAllLines(packageOverridesFile); + var reducer = new FrameworkReducer(); + var frameworkKey = GetFrameworkKey(frameworkName); + var candidateFrameworks = FrameworkPackagesByFramework.Where(pair => pair.Value.ContainsKey(frameworkKey)).Select(pair => pair.Key); + var nearestFramework = reducer.GetNearest(framework, candidateFrameworks); - foreach (var packageOverride in packageOverrides) - { - var packageOverrideParts = packageOverride.Trim().Split('|'); + var frameworkPackages = nearestFramework is null ? + new FrameworkPackages(framework, frameworkName) : + new FrameworkPackages(framework, frameworkName, FrameworkPackagesByFramework[nearestFramework][frameworkKey]); - if (packageOverrideParts.Length == 2) + // packs location : %ProgramFiles%\dotnet\packs + var packsFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "dotnet", "packs", frameworkName + ".Ref"); + if (Directory.Exists(packsFolder)) + { + var packVersionPattern = $"{framework.Version.Major}.{framework.Version.Minor}.*"; + var packDirectories = Directory.GetDirectories(packsFolder, packVersionPattern); + var packageOverridesFile = packDirectories + .Select(d => (Overrides: Path.Combine(d, "data", "PackageOverrides.txt"), Version: ParseVersion(Path.GetFileName(d)))) + .Where(d => File.Exists(d.Overrides)) + .OrderByDescending(d => d.Version) + .FirstOrDefault().Overrides; + + if (packageOverridesFile is not null) { - var packageId = packageOverrideParts[0]; - var packageVersion = ParseVersion(packageOverrideParts[1]); + // Adapted from https://github.com/dotnet/sdk/blob/c3a8f72c3a5491c693ff8e49e7406136a12c3040/src/Tasks/Common/ConflictResolution/PackageOverride.cs#L52-L68 + var packageOverrides = File.ReadAllLines(packageOverridesFile); + + foreach (var packageOverride in packageOverrides) + { + var packageOverrideParts = packageOverride.Trim().Split('|'); - frameworkPackages.Packages[packageId] = packageVersion; + if (packageOverrideParts.Length == 2) + { + var packageId = packageOverrideParts[0]; + var packageVersion = ParseVersion(packageOverrideParts[1]); + + frameworkPackages.Packages[packageId] = packageVersion; + } + } } } @@ -119,4 +168,12 @@ private void Add(string id, string version) IEnumerator> IEnumerable>.GetEnumerator() => this.Packages.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException(); + + internal static class FrameworkNames + { + public const string AspNetCoreApp = "Microsoft.AspNetCore.App"; + public const string NetCoreApp = "Microsoft.NETCore.App"; + public const string NetStandardLibrary = "NETStandard.Library"; + public const string WindowsDesktopApp = "Microsoft.WindowsDesktop.App"; + } } diff --git a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.net5.0.cs b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.net5.0.cs index 0326c7dfb..6b7a63e0a 100644 --- a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.net5.0.cs +++ b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.net5.0.cs @@ -1,6 +1,6 @@ namespace Microsoft.ComponentDetection.Detectors.NuGet; -using global::NuGet.Frameworks; +using static global::NuGet.Frameworks.FrameworkConstants.CommonFrameworks; /// /// Framework packages for net5.0. @@ -9,73 +9,193 @@ internal partial class FrameworkPackages { internal static class NETCoreApp50 { - internal static FrameworkPackages Instance { get; } = new(NuGetFramework.Parse("net5.0"), NETCoreApp31.Instance) + internal static FrameworkPackages Instance { get; } = new(Net50, FrameworkNames.NetCoreApp, NETCoreApp31.Instance) { - { "Microsoft.CSharp", "4.7.0" }, - { "runtime.debian.8-x64.runtime.native.System", "4.3.0" }, - { "runtime.debian.8-x64.runtime.native.System.IO.Compression", "4.3.0" }, - { "runtime.debian.8-x64.runtime.native.System.Net.Http", "4.3.0" }, - { "runtime.debian.8-x64.runtime.native.System.Net.Security", "4.3.0" }, - { "runtime.debian.8-x64.runtime.native.System.Security.Cryptography", "4.3.0" }, - { "runtime.fedora.23-x64.runtime.native.System", "4.3.0" }, - { "runtime.fedora.23-x64.runtime.native.System.IO.Compression", "4.3.0" }, - { "runtime.fedora.23-x64.runtime.native.System.Net.Http", "4.3.0" }, - { "runtime.fedora.23-x64.runtime.native.System.Net.Security", "4.3.0" }, - { "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography", "4.3.0" }, - { "runtime.fedora.24-x64.runtime.native.System", "4.3.0" }, - { "runtime.fedora.24-x64.runtime.native.System.IO.Compression", "4.3.0" }, - { "runtime.fedora.24-x64.runtime.native.System.Net.Http", "4.3.0" }, - { "runtime.fedora.24-x64.runtime.native.System.Net.Security", "4.3.0" }, - { "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography", "4.3.0" }, - { "runtime.opensuse.13.2-x64.runtime.native.System", "4.3.0" }, - { "runtime.opensuse.13.2-x64.runtime.native.System.IO.Compression", "4.3.0" }, - { "runtime.opensuse.13.2-x64.runtime.native.System.Net.Http", "4.3.0" }, - { "runtime.opensuse.13.2-x64.runtime.native.System.Net.Security", "4.3.0" }, - { "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography", "4.3.0" }, - { "runtime.opensuse.42.1-x64.runtime.native.System", "4.3.0" }, - { "runtime.opensuse.42.1-x64.runtime.native.System.IO.Compression", "4.3.0" }, - { "runtime.opensuse.42.1-x64.runtime.native.System.Net.Http", "4.3.0" }, - { "runtime.opensuse.42.1-x64.runtime.native.System.Net.Security", "4.3.0" }, - { "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography", "4.3.0" }, - { "runtime.osx.10.10-x64.runtime.native.System", "4.3.0" }, - { "runtime.osx.10.10-x64.runtime.native.System.IO.Compression", "4.3.0" }, - { "runtime.osx.10.10-x64.runtime.native.System.Net.Http", "4.3.0" }, - { "runtime.osx.10.10-x64.runtime.native.System.Net.Security", "4.3.0" }, - { "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography", "4.3.0" }, - { "runtime.rhel.7-x64.runtime.native.System", "4.3.0" }, - { "runtime.rhel.7-x64.runtime.native.System.IO.Compression", "4.3.0" }, - { "runtime.rhel.7-x64.runtime.native.System.Net.Http", "4.3.0" }, - { "runtime.rhel.7-x64.runtime.native.System.Net.Security", "4.3.0" }, - { "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography", "4.3.0" }, - { "runtime.ubuntu.14.04-x64.runtime.native.System", "4.3.0" }, - { "runtime.ubuntu.14.04-x64.runtime.native.System.IO.Compression", "4.3.0" }, - { "runtime.ubuntu.14.04-x64.runtime.native.System.Net.Http", "4.3.0" }, - { "runtime.ubuntu.14.04-x64.runtime.native.System.Net.Security", "4.3.0" }, - { "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography", "4.3.0" }, - { "runtime.ubuntu.16.04-x64.runtime.native.System", "4.3.0" }, - { "runtime.ubuntu.16.04-x64.runtime.native.System.IO.Compression", "4.3.0" }, - { "runtime.ubuntu.16.04-x64.runtime.native.System.Net.Http", "4.3.0" }, - { "runtime.ubuntu.16.04-x64.runtime.native.System.Net.Security", "4.3.0" }, - { "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography", "4.3.0" }, - { "runtime.ubuntu.16.10-x64.runtime.native.System", "4.3.0" }, - { "runtime.ubuntu.16.10-x64.runtime.native.System.IO.Compression", "4.3.0" }, - { "runtime.ubuntu.16.10-x64.runtime.native.System.Net.Http", "4.3.0" }, - { "runtime.ubuntu.16.10-x64.runtime.native.System.Net.Security", "4.3.0" }, - { "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography", "4.3.0" }, - { "System.Buffers", "4.5.1" }, + { "Microsoft.Win32.Registry", "5.0.0" }, { "System.Collections.Immutable", "5.0.0" }, { "System.ComponentModel.Annotations", "5.0.0" }, { "System.Diagnostics.DiagnosticSource", "5.0.0" }, { "System.Formats.Asn1", "5.0.0" }, + { "System.IO.FileSystem.AccessControl", "5.0.0" }, { "System.Net.Http.Json", "5.0.0" }, { "System.Reflection.DispatchProxy", "4.7.1" }, { "System.Reflection.Metadata", "5.0.0" }, { "System.Runtime.CompilerServices.Unsafe", "5.0.0" }, + { "System.Security.AccessControl", "5.0.0" }, + { "System.Security.Cryptography.OpenSsl", "5.0.0" }, + { "System.Security.Principal.Windows", "5.0.0" }, { "System.Text.Encoding.CodePages", "5.0.0" }, { "System.Text.Encodings.Web", "5.0.0" }, { "System.Text.Json", "5.0.0" }, { "System.Threading.Channels", "5.0.0" }, { "System.Threading.Tasks.Dataflow", "5.0.0" }, }; + + internal static FrameworkPackages AspNetCore { get; } = new(Net50, FrameworkNames.AspNetCoreApp, NETCoreApp31.AspNetCore) + { + { "Microsoft.AspNetCore", "5.0.0" }, + { "Microsoft.AspNetCore.Antiforgery", "5.0.0" }, + { "Microsoft.AspNetCore.Authentication", "5.0.0" }, + { "Microsoft.AspNetCore.Authentication.Abstractions", "5.0.0" }, + { "Microsoft.AspNetCore.Authentication.Cookies", "5.0.0" }, + { "Microsoft.AspNetCore.Authentication.Core", "5.0.0" }, + { "Microsoft.AspNetCore.Authentication.OAuth", "5.0.0" }, + { "Microsoft.AspNetCore.Authorization", "5.0.0" }, + { "Microsoft.AspNetCore.Authorization.Policy", "5.0.0" }, + { "Microsoft.AspNetCore.Components", "5.0.0" }, + { "Microsoft.AspNetCore.Components.Authorization", "5.0.0" }, + { "Microsoft.AspNetCore.Components.Forms", "5.0.0" }, + { "Microsoft.AspNetCore.Components.Server", "5.0.0" }, + { "Microsoft.AspNetCore.Components.Web", "5.0.0" }, + { "Microsoft.AspNetCore.Connections.Abstractions", "5.0.0" }, + { "Microsoft.AspNetCore.CookiePolicy", "5.0.0" }, + { "Microsoft.AspNetCore.Cors", "5.0.0" }, + { "Microsoft.AspNetCore.Cryptography.Internal", "5.0.0" }, + { "Microsoft.AspNetCore.Cryptography.KeyDerivation", "5.0.0" }, + { "Microsoft.AspNetCore.DataProtection", "5.0.0" }, + { "Microsoft.AspNetCore.DataProtection.Abstractions", "5.0.0" }, + { "Microsoft.AspNetCore.DataProtection.Extensions", "5.0.0" }, + { "Microsoft.AspNetCore.Diagnostics", "5.0.0" }, + { "Microsoft.AspNetCore.Diagnostics.Abstractions", "5.0.0" }, + { "Microsoft.AspNetCore.Diagnostics.HealthChecks", "5.0.0" }, + { "Microsoft.AspNetCore.HostFiltering", "5.0.0" }, + { "Microsoft.AspNetCore.Hosting", "5.0.0" }, + { "Microsoft.AspNetCore.Hosting.Abstractions", "5.0.0" }, + { "Microsoft.AspNetCore.Hosting.Server.Abstractions", "5.0.0" }, + { "Microsoft.AspNetCore.Html.Abstractions", "5.0.0" }, + { "Microsoft.AspNetCore.Http", "5.0.0" }, + { "Microsoft.AspNetCore.Http.Abstractions", "5.0.0" }, + { "Microsoft.AspNetCore.Http.Connections", "5.0.0" }, + { "Microsoft.AspNetCore.Http.Connections.Common", "5.0.0" }, + { "Microsoft.AspNetCore.Http.Extensions", "5.0.0" }, + { "Microsoft.AspNetCore.Http.Features", "5.0.0" }, + { "Microsoft.AspNetCore.HttpOverrides", "5.0.0" }, + { "Microsoft.AspNetCore.HttpsPolicy", "5.0.0" }, + { "Microsoft.AspNetCore.Identity", "5.0.0" }, + { "Microsoft.AspNetCore.Localization", "5.0.0" }, + { "Microsoft.AspNetCore.Localization.Routing", "5.0.0" }, + { "Microsoft.AspNetCore.Metadata", "5.0.0" }, + { "Microsoft.AspNetCore.Mvc", "5.0.0" }, + { "Microsoft.AspNetCore.Mvc.Abstractions", "5.0.0" }, + { "Microsoft.AspNetCore.Mvc.ApiExplorer", "5.0.0" }, + { "Microsoft.AspNetCore.Mvc.Core", "5.0.0" }, + { "Microsoft.AspNetCore.Mvc.Cors", "5.0.0" }, + { "Microsoft.AspNetCore.Mvc.DataAnnotations", "5.0.0" }, + { "Microsoft.AspNetCore.Mvc.Formatters.Json", "5.0.0" }, + { "Microsoft.AspNetCore.Mvc.Formatters.Xml", "5.0.0" }, + { "Microsoft.AspNetCore.Mvc.Localization", "5.0.0" }, + { "Microsoft.AspNetCore.Mvc.Razor", "5.0.0" }, + { "Microsoft.AspNetCore.Mvc.RazorPages", "5.0.0" }, + { "Microsoft.AspNetCore.Mvc.TagHelpers", "5.0.0" }, + { "Microsoft.AspNetCore.Mvc.ViewFeatures", "5.0.0" }, + { "Microsoft.AspNetCore.Razor", "5.0.0" }, + { "Microsoft.AspNetCore.Razor.Runtime", "5.0.0" }, + { "Microsoft.AspNetCore.ResponseCaching", "5.0.0" }, + { "Microsoft.AspNetCore.ResponseCaching.Abstractions", "5.0.0" }, + { "Microsoft.AspNetCore.ResponseCompression", "5.0.0" }, + { "Microsoft.AspNetCore.Rewrite", "5.0.0" }, + { "Microsoft.AspNetCore.Routing", "5.0.0" }, + { "Microsoft.AspNetCore.Routing.Abstractions", "5.0.0" }, + { "Microsoft.AspNetCore.Server.HttpSys", "5.0.0" }, + { "Microsoft.AspNetCore.Server.IIS", "5.0.0" }, + { "Microsoft.AspNetCore.Server.IISIntegration", "5.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel", "5.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel.Core", "5.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets", "5.0.0" }, + { "Microsoft.AspNetCore.Session", "5.0.0" }, + { "Microsoft.AspNetCore.SignalR", "5.0.0" }, + { "Microsoft.AspNetCore.SignalR.Common", "5.0.0" }, + { "Microsoft.AspNetCore.SignalR.Core", "5.0.0" }, + { "Microsoft.AspNetCore.SignalR.Protocols.Json", "5.0.0" }, + { "Microsoft.AspNetCore.StaticFiles", "5.0.0" }, + { "Microsoft.AspNetCore.WebSockets", "5.0.0" }, + { "Microsoft.AspNetCore.WebUtilities", "5.0.0" }, + { "Microsoft.Extensions.Caching.Abstractions", "5.0.0" }, + { "Microsoft.Extensions.Caching.Memory", "5.0.0" }, + { "Microsoft.Extensions.Configuration", "5.0.0" }, + { "Microsoft.Extensions.Configuration.Abstractions", "5.0.0" }, + { "Microsoft.Extensions.Configuration.Binder", "5.0.0" }, + { "Microsoft.Extensions.Configuration.CommandLine", "5.0.0" }, + { "Microsoft.Extensions.Configuration.EnvironmentVariables", "5.0.0" }, + { "Microsoft.Extensions.Configuration.FileExtensions", "5.0.0" }, + { "Microsoft.Extensions.Configuration.Ini", "5.0.0" }, + { "Microsoft.Extensions.Configuration.Json", "5.0.0" }, + { "Microsoft.Extensions.Configuration.KeyPerFile", "5.0.0" }, + { "Microsoft.Extensions.Configuration.UserSecrets", "5.0.0" }, + { "Microsoft.Extensions.Configuration.Xml", "5.0.0" }, + { "Microsoft.Extensions.DependencyInjection", "5.0.0" }, + { "Microsoft.Extensions.DependencyInjection.Abstractions", "5.0.0" }, + { "Microsoft.Extensions.Diagnostics.HealthChecks", "5.0.0" }, + { "Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions", "5.0.0" }, + { "Microsoft.Extensions.FileProviders.Abstractions", "5.0.0" }, + { "Microsoft.Extensions.FileProviders.Composite", "5.0.0" }, + { "Microsoft.Extensions.FileProviders.Embedded", "5.0.0" }, + { "Microsoft.Extensions.FileProviders.Physical", "5.0.0" }, + { "Microsoft.Extensions.FileSystemGlobbing", "5.0.0" }, + { "Microsoft.Extensions.Hosting", "5.0.0" }, + { "Microsoft.Extensions.Hosting.Abstractions", "5.0.0" }, + { "Microsoft.Extensions.Http", "5.0.0" }, + { "Microsoft.Extensions.Identity.Core", "5.0.0" }, + { "Microsoft.Extensions.Identity.Stores", "5.0.0" }, + { "Microsoft.Extensions.Localization", "5.0.0" }, + { "Microsoft.Extensions.Localization.Abstractions", "5.0.0" }, + { "Microsoft.Extensions.Logging", "5.0.0" }, + { "Microsoft.Extensions.Logging.Abstractions", "5.0.0" }, + { "Microsoft.Extensions.Logging.Configuration", "5.0.0" }, + { "Microsoft.Extensions.Logging.Console", "5.0.0" }, + { "Microsoft.Extensions.Logging.Debug", "5.0.0" }, + { "Microsoft.Extensions.Logging.EventLog", "5.0.0" }, + { "Microsoft.Extensions.Logging.EventSource", "5.0.0" }, + { "Microsoft.Extensions.Logging.TraceSource", "5.0.0" }, + { "Microsoft.Extensions.ObjectPool", "5.0.0" }, + { "Microsoft.Extensions.Options", "5.0.0" }, + { "Microsoft.Extensions.Options.ConfigurationExtensions", "5.0.0" }, + { "Microsoft.Extensions.Options.DataAnnotations", "5.0.0" }, + { "Microsoft.Extensions.Primitives", "5.0.0" }, + { "Microsoft.Extensions.WebEncoders", "5.0.0" }, + { "Microsoft.JSInterop", "5.0.0" }, + { "Microsoft.Net.Http.Headers", "5.0.0" }, + { "Microsoft.Win32.Registry", "5.0.0" }, + { "Microsoft.Win32.SystemEvents", "5.0.0" }, + { "System.Diagnostics.EventLog", "5.0.0" }, + { "System.Drawing.Common", "5.0.0" }, + { "System.IO.Pipelines", "5.0.0" }, + { "System.Security.AccessControl", "5.0.0" }, + { "System.Security.Cryptography.Cng", "5.0.0" }, + { "System.Security.Cryptography.Pkcs", "5.0.0" }, + { "System.Security.Cryptography.Xml", "5.0.0" }, + { "System.Security.Permissions", "5.0.0" }, + { "System.Security.Principal.Windows", "5.0.0" }, + { "System.Windows.Extensions", "5.0.0" }, + }; + + internal static FrameworkPackages WindowsDesktop { get; } = new(Net50, FrameworkNames.WindowsDesktopApp, NETCoreApp31.WindowsDesktop) + { + { "Microsoft.VisualBasic", "10.3.0" }, + { "Microsoft.Win32.Registry", "5.0.0" }, + { "Microsoft.Win32.Registry.AccessControl", "5.0.0" }, + { "Microsoft.Win32.SystemEvents", "5.0.0" }, + { "System.CodeDom", "5.0.0" }, + { "System.Configuration.ConfigurationManager", "5.0.0" }, + { "System.Diagnostics.EventLog", "5.0.0" }, + { "System.Diagnostics.PerformanceCounter", "5.0.0" }, + { "System.Drawing.Common", "5.0.0" }, + { "System.Formats.Asn1", "5.0.0" }, + { "System.IO.FileSystem.AccessControl", "5.0.0" }, + { "System.IO.Packaging", "5.0.0" }, + { "System.IO.Pipes.AccessControl", "5.0.0" }, + { "System.Resources.Extensions", "5.0.0" }, + { "System.Security.AccessControl", "5.0.0" }, + { "System.Security.Cryptography.Cng", "5.0.0" }, + { "System.Security.Cryptography.Pkcs", "5.0.0" }, + { "System.Security.Cryptography.ProtectedData", "5.0.0" }, + { "System.Security.Cryptography.Xml", "5.0.0" }, + { "System.Security.Permissions", "5.0.0" }, + { "System.Security.Principal.Windows", "5.0.0" }, + { "System.Threading.AccessControl", "5.0.0" }, + { "System.Windows.Extensions", "5.0.0" }, + }; + + internal static void Register() => FrameworkPackages.Register(Instance, AspNetCore, WindowsDesktop); } } diff --git a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.net6.0.cs b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.net6.0.cs index ca5b2d92b..dde6aa768 100644 --- a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.net6.0.cs +++ b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.net6.0.cs @@ -1,6 +1,6 @@ namespace Microsoft.ComponentDetection.Detectors.NuGet; -using global::NuGet.Frameworks; +using static global::NuGet.Frameworks.FrameworkConstants.CommonFrameworks; /// /// Framework packages for net6.0. @@ -9,26 +9,175 @@ internal partial class FrameworkPackages { internal static class NETCoreApp60 { - internal static FrameworkPackages Instance { get; } = new(NuGetFramework.Parse("net6.0"), NETCoreApp50.Instance) + internal static FrameworkPackages Instance { get; } = new(Net60, FrameworkNames.NetCoreApp, NETCoreApp50.Instance) { - { "Microsoft.Win32.Registry", "5.0.0" }, { "System.Collections.Immutable", "6.0.0" }, - { "System.Diagnostics.DiagnosticSource", "6.0.1" }, - { "System.Formats.Asn1", "6.0.1" }, - { "System.IO.FileSystem.AccessControl", "5.0.0" }, - { "System.IO.Pipes.AccessControl", "5.0.0" }, - { "System.Net.Http.Json", "6.0.1" }, - { "System.Reflection.Metadata", "6.0.1" }, + { "System.Diagnostics.DiagnosticSource", "6.0.0" }, + { "System.Formats.Asn1", "6.0.0" }, + { "System.Net.Http.Json", "6.0.0" }, + { "System.Reflection.Metadata", "6.0.0" }, { "System.Runtime.CompilerServices.Unsafe", "6.0.0" }, - { "System.Security.AccessControl", "6.0.1" }, - { "System.Security.Cryptography.Cng", "5.0.0" }, - { "System.Security.Cryptography.OpenSsl", "5.0.0" }, - { "System.Security.Principal.Windows", "5.0.0" }, + { "System.Security.AccessControl", "6.0.0" }, { "System.Text.Encoding.CodePages", "6.0.0" }, { "System.Text.Encodings.Web", "6.0.0" }, - { "System.Text.Json", "6.0.9" }, + { "System.Text.Json", "6.0.0" }, { "System.Threading.Channels", "6.0.0" }, { "System.Threading.Tasks.Dataflow", "6.0.0" }, }; + + internal static FrameworkPackages AspNetCore { get; } = new(Net60, FrameworkNames.AspNetCoreApp, NETCoreApp50.AspNetCore) + { + { "Microsoft.AspNetCore", "6.0.0" }, + { "Microsoft.AspNetCore.Antiforgery", "6.0.0" }, + { "Microsoft.AspNetCore.Authentication", "6.0.0" }, + { "Microsoft.AspNetCore.Authentication.Abstractions", "6.0.0" }, + { "Microsoft.AspNetCore.Authentication.Cookies", "6.0.0" }, + { "Microsoft.AspNetCore.Authentication.Core", "6.0.0" }, + { "Microsoft.AspNetCore.Authentication.OAuth", "6.0.0" }, + { "Microsoft.AspNetCore.Authorization", "6.0.0" }, + { "Microsoft.AspNetCore.Authorization.Policy", "6.0.0" }, + { "Microsoft.AspNetCore.Components", "6.0.0" }, + { "Microsoft.AspNetCore.Components.Authorization", "6.0.0" }, + { "Microsoft.AspNetCore.Components.Forms", "6.0.0" }, + { "Microsoft.AspNetCore.Components.Server", "6.0.0" }, + { "Microsoft.AspNetCore.Components.Web", "6.0.0" }, + { "Microsoft.AspNetCore.Connections.Abstractions", "6.0.0" }, + { "Microsoft.AspNetCore.CookiePolicy", "6.0.0" }, + { "Microsoft.AspNetCore.Cors", "6.0.0" }, + { "Microsoft.AspNetCore.Cryptography.Internal", "6.0.0" }, + { "Microsoft.AspNetCore.Cryptography.KeyDerivation", "6.0.0" }, + { "Microsoft.AspNetCore.DataProtection", "6.0.0" }, + { "Microsoft.AspNetCore.DataProtection.Abstractions", "6.0.0" }, + { "Microsoft.AspNetCore.DataProtection.Extensions", "6.0.0" }, + { "Microsoft.AspNetCore.Diagnostics", "6.0.0" }, + { "Microsoft.AspNetCore.Diagnostics.Abstractions", "6.0.0" }, + { "Microsoft.AspNetCore.Diagnostics.HealthChecks", "6.0.0" }, + { "Microsoft.AspNetCore.HostFiltering", "6.0.0" }, + { "Microsoft.AspNetCore.Hosting", "6.0.0" }, + { "Microsoft.AspNetCore.Hosting.Abstractions", "6.0.0" }, + { "Microsoft.AspNetCore.Hosting.Server.Abstractions", "6.0.0" }, + { "Microsoft.AspNetCore.Html.Abstractions", "6.0.0" }, + { "Microsoft.AspNetCore.Http", "6.0.0" }, + { "Microsoft.AspNetCore.Http.Abstractions", "6.0.0" }, + { "Microsoft.AspNetCore.Http.Connections", "6.0.0" }, + { "Microsoft.AspNetCore.Http.Connections.Common", "6.0.0" }, + { "Microsoft.AspNetCore.Http.Extensions", "6.0.0" }, + { "Microsoft.AspNetCore.Http.Features", "6.0.0" }, + { "Microsoft.AspNetCore.Http.Results", "6.0.0" }, + { "Microsoft.AspNetCore.HttpLogging", "6.0.0" }, + { "Microsoft.AspNetCore.HttpOverrides", "6.0.0" }, + { "Microsoft.AspNetCore.HttpsPolicy", "6.0.0" }, + { "Microsoft.AspNetCore.Identity", "6.0.0" }, + { "Microsoft.AspNetCore.Localization", "6.0.0" }, + { "Microsoft.AspNetCore.Localization.Routing", "6.0.0" }, + { "Microsoft.AspNetCore.Metadata", "6.0.0" }, + { "Microsoft.AspNetCore.Mvc", "6.0.0" }, + { "Microsoft.AspNetCore.Mvc.Abstractions", "6.0.0" }, + { "Microsoft.AspNetCore.Mvc.ApiExplorer", "6.0.0" }, + { "Microsoft.AspNetCore.Mvc.Core", "6.0.0" }, + { "Microsoft.AspNetCore.Mvc.Cors", "6.0.0" }, + { "Microsoft.AspNetCore.Mvc.DataAnnotations", "6.0.0" }, + { "Microsoft.AspNetCore.Mvc.Formatters.Json", "6.0.0" }, + { "Microsoft.AspNetCore.Mvc.Formatters.Xml", "6.0.0" }, + { "Microsoft.AspNetCore.Mvc.Localization", "6.0.0" }, + { "Microsoft.AspNetCore.Mvc.Razor", "6.0.0" }, + { "Microsoft.AspNetCore.Mvc.RazorPages", "6.0.0" }, + { "Microsoft.AspNetCore.Mvc.TagHelpers", "6.0.0" }, + { "Microsoft.AspNetCore.Mvc.ViewFeatures", "6.0.0" }, + { "Microsoft.AspNetCore.Razor", "6.0.0" }, + { "Microsoft.AspNetCore.Razor.Runtime", "6.0.0" }, + { "Microsoft.AspNetCore.ResponseCaching", "6.0.0" }, + { "Microsoft.AspNetCore.ResponseCaching.Abstractions", "6.0.0" }, + { "Microsoft.AspNetCore.ResponseCompression", "6.0.0" }, + { "Microsoft.AspNetCore.Rewrite", "6.0.0" }, + { "Microsoft.AspNetCore.Routing", "6.0.0" }, + { "Microsoft.AspNetCore.Routing.Abstractions", "6.0.0" }, + { "Microsoft.AspNetCore.Server.HttpSys", "6.0.0" }, + { "Microsoft.AspNetCore.Server.IIS", "6.0.0" }, + { "Microsoft.AspNetCore.Server.IISIntegration", "6.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel", "6.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel.Core", "6.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel.Transport.Quic", "6.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets", "6.0.0" }, + { "Microsoft.AspNetCore.Session", "6.0.0" }, + { "Microsoft.AspNetCore.SignalR", "6.0.0" }, + { "Microsoft.AspNetCore.SignalR.Common", "6.0.0" }, + { "Microsoft.AspNetCore.SignalR.Core", "6.0.0" }, + { "Microsoft.AspNetCore.SignalR.Protocols.Json", "6.0.0" }, + { "Microsoft.AspNetCore.StaticFiles", "6.0.0" }, + { "Microsoft.AspNetCore.WebSockets", "6.0.0" }, + { "Microsoft.AspNetCore.WebUtilities", "6.0.0" }, + { "Microsoft.Extensions.Caching.Abstractions", "6.0.0" }, + { "Microsoft.Extensions.Caching.Memory", "6.0.0" }, + { "Microsoft.Extensions.Configuration", "6.0.0" }, + { "Microsoft.Extensions.Configuration.Abstractions", "6.0.0" }, + { "Microsoft.Extensions.Configuration.Binder", "6.0.0" }, + { "Microsoft.Extensions.Configuration.CommandLine", "6.0.0" }, + { "Microsoft.Extensions.Configuration.EnvironmentVariables", "6.0.0" }, + { "Microsoft.Extensions.Configuration.FileExtensions", "6.0.0" }, + { "Microsoft.Extensions.Configuration.Ini", "6.0.0" }, + { "Microsoft.Extensions.Configuration.Json", "6.0.0" }, + { "Microsoft.Extensions.Configuration.KeyPerFile", "6.0.0" }, + { "Microsoft.Extensions.Configuration.UserSecrets", "6.0.0" }, + { "Microsoft.Extensions.Configuration.Xml", "6.0.0" }, + { "Microsoft.Extensions.DependencyInjection", "6.0.0" }, + { "Microsoft.Extensions.DependencyInjection.Abstractions", "6.0.0" }, + { "Microsoft.Extensions.Diagnostics.HealthChecks", "6.0.0" }, + { "Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions", "6.0.0" }, + { "Microsoft.Extensions.Features", "6.0.0" }, + { "Microsoft.Extensions.FileProviders.Abstractions", "6.0.0" }, + { "Microsoft.Extensions.FileProviders.Composite", "6.0.0" }, + { "Microsoft.Extensions.FileProviders.Embedded", "6.0.0" }, + { "Microsoft.Extensions.FileProviders.Physical", "6.0.0" }, + { "Microsoft.Extensions.FileSystemGlobbing", "6.0.0" }, + { "Microsoft.Extensions.Hosting", "6.0.0" }, + { "Microsoft.Extensions.Hosting.Abstractions", "6.0.0" }, + { "Microsoft.Extensions.Http", "6.0.0" }, + { "Microsoft.Extensions.Identity.Core", "6.0.0" }, + { "Microsoft.Extensions.Identity.Stores", "6.0.0" }, + { "Microsoft.Extensions.Localization", "6.0.0" }, + { "Microsoft.Extensions.Localization.Abstractions", "6.0.0" }, + { "Microsoft.Extensions.Logging", "6.0.0" }, + { "Microsoft.Extensions.Logging.Abstractions", "6.0.0" }, + { "Microsoft.Extensions.Logging.Configuration", "6.0.0" }, + { "Microsoft.Extensions.Logging.Console", "6.0.0" }, + { "Microsoft.Extensions.Logging.Debug", "6.0.0" }, + { "Microsoft.Extensions.Logging.EventLog", "6.0.0" }, + { "Microsoft.Extensions.Logging.EventSource", "6.0.0" }, + { "Microsoft.Extensions.Logging.TraceSource", "6.0.0" }, + { "Microsoft.Extensions.ObjectPool", "6.0.0" }, + { "Microsoft.Extensions.Options", "6.0.0" }, + { "Microsoft.Extensions.Options.ConfigurationExtensions", "6.0.0" }, + { "Microsoft.Extensions.Options.DataAnnotations", "6.0.0" }, + { "Microsoft.Extensions.Primitives", "6.0.0" }, + { "Microsoft.Extensions.WebEncoders", "6.0.0" }, + { "Microsoft.JSInterop", "6.0.0" }, + { "Microsoft.Net.Http.Headers", "6.0.0" }, + { "System.Diagnostics.EventLog", "6.0.0" }, + { "System.IO.Pipelines", "6.0.0" }, + { "System.Security.Cryptography.Pkcs", "6.0.0" }, + { "System.Security.Cryptography.Xml", "6.0.0" }, + }; + + internal static FrameworkPackages WindowsDesktop { get; } = new(Net60, FrameworkNames.WindowsDesktopApp, NETCoreApp50.WindowsDesktop) + { + { "Microsoft.Win32.Registry.AccessControl", "6.0.0" }, + { "Microsoft.Win32.SystemEvents", "6.0.0" }, + { "System.CodeDom", "6.0.0" }, + { "System.Configuration.ConfigurationManager", "6.0.0" }, + { "System.Diagnostics.EventLog", "6.0.0" }, + { "System.Diagnostics.PerformanceCounter", "6.0.0" }, + { "System.Drawing.Common", "6.0.0" }, + { "System.IO.Packaging", "6.0.0" }, + { "System.Resources.Extensions", "6.0.0" }, + { "System.Security.Cryptography.Pkcs", "6.0.0" }, + { "System.Security.Cryptography.ProtectedData", "6.0.0" }, + { "System.Security.Cryptography.Xml", "6.0.0" }, + { "System.Security.Permissions", "6.0.0" }, + { "System.Threading.AccessControl", "6.0.0" }, + { "System.Windows.Extensions", "6.0.0" }, + }; + + internal static void Register() => FrameworkPackages.Register(Instance, AspNetCore, WindowsDesktop); } } diff --git a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.net7.0.cs b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.net7.0.cs index 206d1a194..4e8d49af3 100644 --- a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.net7.0.cs +++ b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.net7.0.cs @@ -1,6 +1,6 @@ namespace Microsoft.ComponentDetection.Detectors.NuGet; -using global::NuGet.Frameworks; +using static global::NuGet.Frameworks.FrameworkConstants.CommonFrameworks; /// /// Framework packages for net7.0. @@ -9,18 +9,178 @@ internal partial class FrameworkPackages { internal static class NETCoreApp70 { - internal static FrameworkPackages Instance { get; } = new(NuGetFramework.Parse("net7.0"), NETCoreApp60.Instance) + internal static FrameworkPackages Instance { get; } = new(Net70, FrameworkNames.NetCoreApp, NETCoreApp60.Instance) { { "System.Collections.Immutable", "7.0.0" }, { "System.Diagnostics.DiagnosticSource", "7.0.2" }, { "System.Formats.Asn1", "7.0.0" }, { "System.Net.Http.Json", "7.0.1" }, { "System.Reflection.Metadata", "7.0.2" }, + { "System.Security.AccessControl", "6.0.1" }, { "System.Text.Encoding.CodePages", "7.0.0" }, { "System.Text.Encodings.Web", "7.0.0" }, { "System.Text.Json", "7.0.4" }, { "System.Threading.Channels", "7.0.0" }, { "System.Threading.Tasks.Dataflow", "7.0.0" }, }; + + internal static FrameworkPackages AspNetCore { get; } = new(Net70, FrameworkNames.AspNetCoreApp, NETCoreApp60.AspNetCore) + { + { "Microsoft.AspNetCore", "7.0.0" }, + { "Microsoft.AspNetCore.Antiforgery", "7.0.0" }, + { "Microsoft.AspNetCore.Authentication", "7.0.0" }, + { "Microsoft.AspNetCore.Authentication.Abstractions", "7.0.0" }, + { "Microsoft.AspNetCore.Authentication.Cookies", "7.0.0" }, + { "Microsoft.AspNetCore.Authentication.Core", "7.0.0" }, + { "Microsoft.AspNetCore.Authentication.OAuth", "7.0.0" }, + { "Microsoft.AspNetCore.Authorization", "7.0.0" }, + { "Microsoft.AspNetCore.Authorization.Policy", "7.0.0" }, + { "Microsoft.AspNetCore.Components", "7.0.0" }, + { "Microsoft.AspNetCore.Components.Authorization", "7.0.0" }, + { "Microsoft.AspNetCore.Components.Forms", "7.0.0" }, + { "Microsoft.AspNetCore.Components.Server", "7.0.0" }, + { "Microsoft.AspNetCore.Components.Web", "7.0.0" }, + { "Microsoft.AspNetCore.Connections.Abstractions", "7.0.0" }, + { "Microsoft.AspNetCore.CookiePolicy", "7.0.0" }, + { "Microsoft.AspNetCore.Cors", "7.0.0" }, + { "Microsoft.AspNetCore.Cryptography.Internal", "7.0.0" }, + { "Microsoft.AspNetCore.Cryptography.KeyDerivation", "7.0.0" }, + { "Microsoft.AspNetCore.DataProtection", "7.0.0" }, + { "Microsoft.AspNetCore.DataProtection.Abstractions", "7.0.0" }, + { "Microsoft.AspNetCore.DataProtection.Extensions", "7.0.0" }, + { "Microsoft.AspNetCore.Diagnostics", "7.0.0" }, + { "Microsoft.AspNetCore.Diagnostics.Abstractions", "7.0.0" }, + { "Microsoft.AspNetCore.Diagnostics.HealthChecks", "7.0.0" }, + { "Microsoft.AspNetCore.HostFiltering", "7.0.0" }, + { "Microsoft.AspNetCore.Hosting", "7.0.0" }, + { "Microsoft.AspNetCore.Hosting.Abstractions", "7.0.0" }, + { "Microsoft.AspNetCore.Hosting.Server.Abstractions", "7.0.0" }, + { "Microsoft.AspNetCore.Html.Abstractions", "7.0.0" }, + { "Microsoft.AspNetCore.Http", "7.0.0" }, + { "Microsoft.AspNetCore.Http.Abstractions", "7.0.0" }, + { "Microsoft.AspNetCore.Http.Connections", "7.0.0" }, + { "Microsoft.AspNetCore.Http.Connections.Common", "7.0.0" }, + { "Microsoft.AspNetCore.Http.Extensions", "7.0.0" }, + { "Microsoft.AspNetCore.Http.Features", "7.0.0" }, + { "Microsoft.AspNetCore.Http.Results", "7.0.0" }, + { "Microsoft.AspNetCore.HttpLogging", "7.0.0" }, + { "Microsoft.AspNetCore.HttpOverrides", "7.0.0" }, + { "Microsoft.AspNetCore.HttpsPolicy", "7.0.0" }, + { "Microsoft.AspNetCore.Identity", "7.0.0" }, + { "Microsoft.AspNetCore.Localization", "7.0.0" }, + { "Microsoft.AspNetCore.Localization.Routing", "7.0.0" }, + { "Microsoft.AspNetCore.Metadata", "7.0.0" }, + { "Microsoft.AspNetCore.Mvc", "7.0.0" }, + { "Microsoft.AspNetCore.Mvc.Abstractions", "7.0.0" }, + { "Microsoft.AspNetCore.Mvc.ApiExplorer", "7.0.0" }, + { "Microsoft.AspNetCore.Mvc.Core", "7.0.0" }, + { "Microsoft.AspNetCore.Mvc.Cors", "7.0.0" }, + { "Microsoft.AspNetCore.Mvc.DataAnnotations", "7.0.0" }, + { "Microsoft.AspNetCore.Mvc.Formatters.Json", "7.0.0" }, + { "Microsoft.AspNetCore.Mvc.Formatters.Xml", "7.0.0" }, + { "Microsoft.AspNetCore.Mvc.Localization", "7.0.0" }, + { "Microsoft.AspNetCore.Mvc.Razor", "7.0.0" }, + { "Microsoft.AspNetCore.Mvc.RazorPages", "7.0.0" }, + { "Microsoft.AspNetCore.Mvc.TagHelpers", "7.0.0" }, + { "Microsoft.AspNetCore.Mvc.ViewFeatures", "7.0.0" }, + { "Microsoft.AspNetCore.OutputCaching", "7.0.0" }, + { "Microsoft.AspNetCore.RateLimiting", "7.0.0" }, + { "Microsoft.AspNetCore.Razor", "7.0.0" }, + { "Microsoft.AspNetCore.Razor.Runtime", "7.0.0" }, + { "Microsoft.AspNetCore.RequestDecompression", "7.0.0" }, + { "Microsoft.AspNetCore.ResponseCaching", "7.0.0" }, + { "Microsoft.AspNetCore.ResponseCaching.Abstractions", "7.0.0" }, + { "Microsoft.AspNetCore.ResponseCompression", "7.0.0" }, + { "Microsoft.AspNetCore.Rewrite", "7.0.0" }, + { "Microsoft.AspNetCore.Routing", "7.0.0" }, + { "Microsoft.AspNetCore.Routing.Abstractions", "7.0.0" }, + { "Microsoft.AspNetCore.Server.HttpSys", "7.0.0" }, + { "Microsoft.AspNetCore.Server.IIS", "7.0.0" }, + { "Microsoft.AspNetCore.Server.IISIntegration", "7.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel", "7.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel.Core", "7.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel.Transport.Quic", "7.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets", "7.0.0" }, + { "Microsoft.AspNetCore.Session", "7.0.0" }, + { "Microsoft.AspNetCore.SignalR", "7.0.0" }, + { "Microsoft.AspNetCore.SignalR.Common", "7.0.0" }, + { "Microsoft.AspNetCore.SignalR.Core", "7.0.0" }, + { "Microsoft.AspNetCore.SignalR.Protocols.Json", "7.0.0" }, + { "Microsoft.AspNetCore.StaticFiles", "7.0.0" }, + { "Microsoft.AspNetCore.WebSockets", "7.0.0" }, + { "Microsoft.AspNetCore.WebUtilities", "7.0.0" }, + { "Microsoft.Extensions.Caching.Abstractions", "7.0.0" }, + { "Microsoft.Extensions.Caching.Memory", "7.0.0" }, + { "Microsoft.Extensions.Configuration", "7.0.0" }, + { "Microsoft.Extensions.Configuration.Abstractions", "7.0.0" }, + { "Microsoft.Extensions.Configuration.Binder", "7.0.0" }, + { "Microsoft.Extensions.Configuration.CommandLine", "7.0.0" }, + { "Microsoft.Extensions.Configuration.EnvironmentVariables", "7.0.0" }, + { "Microsoft.Extensions.Configuration.FileExtensions", "7.0.0" }, + { "Microsoft.Extensions.Configuration.Ini", "7.0.0" }, + { "Microsoft.Extensions.Configuration.Json", "7.0.0" }, + { "Microsoft.Extensions.Configuration.KeyPerFile", "7.0.0" }, + { "Microsoft.Extensions.Configuration.UserSecrets", "7.0.0" }, + { "Microsoft.Extensions.Configuration.Xml", "7.0.0" }, + { "Microsoft.Extensions.DependencyInjection", "7.0.0" }, + { "Microsoft.Extensions.DependencyInjection.Abstractions", "7.0.0" }, + { "Microsoft.Extensions.Diagnostics.HealthChecks", "7.0.0" }, + { "Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions", "7.0.0" }, + { "Microsoft.Extensions.Features", "7.0.0" }, + { "Microsoft.Extensions.FileProviders.Abstractions", "7.0.0" }, + { "Microsoft.Extensions.FileProviders.Composite", "7.0.0" }, + { "Microsoft.Extensions.FileProviders.Embedded", "7.0.0" }, + { "Microsoft.Extensions.FileProviders.Physical", "7.0.0" }, + { "Microsoft.Extensions.FileSystemGlobbing", "7.0.0" }, + { "Microsoft.Extensions.Hosting", "7.0.0" }, + { "Microsoft.Extensions.Hosting.Abstractions", "7.0.0" }, + { "Microsoft.Extensions.Http", "7.0.0" }, + { "Microsoft.Extensions.Identity.Core", "7.0.0" }, + { "Microsoft.Extensions.Identity.Stores", "7.0.0" }, + { "Microsoft.Extensions.Localization", "7.0.0" }, + { "Microsoft.Extensions.Localization.Abstractions", "7.0.0" }, + { "Microsoft.Extensions.Logging", "7.0.0" }, + { "Microsoft.Extensions.Logging.Abstractions", "7.0.0" }, + { "Microsoft.Extensions.Logging.Configuration", "7.0.0" }, + { "Microsoft.Extensions.Logging.Console", "7.0.0" }, + { "Microsoft.Extensions.Logging.Debug", "7.0.0" }, + { "Microsoft.Extensions.Logging.EventLog", "7.0.0" }, + { "Microsoft.Extensions.Logging.EventSource", "7.0.0" }, + { "Microsoft.Extensions.Logging.TraceSource", "7.0.0" }, + { "Microsoft.Extensions.ObjectPool", "7.0.0" }, + { "Microsoft.Extensions.Options", "7.0.0" }, + { "Microsoft.Extensions.Options.ConfigurationExtensions", "7.0.0" }, + { "Microsoft.Extensions.Options.DataAnnotations", "7.0.0" }, + { "Microsoft.Extensions.Primitives", "7.0.0" }, + { "Microsoft.Extensions.WebEncoders", "7.0.0" }, + { "Microsoft.JSInterop", "7.0.0" }, + { "Microsoft.Net.Http.Headers", "7.0.0" }, + { "System.Diagnostics.EventLog", "7.0.0" }, + { "System.IO.Pipelines", "7.0.0" }, + { "System.Security.Cryptography.Pkcs", "7.0.0" }, + { "System.Security.Cryptography.Xml", "7.0.0" }, + { "System.Threading.RateLimiting", "7.0.0" }, + }; + + internal static FrameworkPackages WindowsDesktop { get; } = new(Net70, FrameworkNames.WindowsDesktopApp, NETCoreApp60.WindowsDesktop) + { + { "Microsoft.Win32.Registry.AccessControl", "7.0.0" }, + { "Microsoft.Win32.SystemEvents", "7.0.0" }, + { "System.CodeDom", "7.0.0" }, + { "System.Configuration.ConfigurationManager", "7.0.0" }, + { "System.Diagnostics.EventLog", "7.0.0" }, + { "System.Diagnostics.PerformanceCounter", "7.0.0" }, + { "System.Drawing.Common", "7.0.0" }, + { "System.IO.Packaging", "7.0.0" }, + { "System.Resources.Extensions", "7.0.0" }, + { "System.Security.Cryptography.Pkcs", "7.0.0" }, + { "System.Security.Cryptography.ProtectedData", "7.0.0" }, + { "System.Security.Cryptography.Xml", "7.0.0" }, + { "System.Security.Permissions", "7.0.0" }, + { "System.Threading.AccessControl", "7.0.0" }, + { "System.Windows.Extensions", "7.0.0" }, + }; + + internal static void Register() => FrameworkPackages.Register(Instance, AspNetCore, WindowsDesktop); } } diff --git a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.net8.0.cs b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.net8.0.cs index 86a273591..f329bcdf7 100644 --- a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.net8.0.cs +++ b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.net8.0.cs @@ -1,6 +1,6 @@ namespace Microsoft.ComponentDetection.Detectors.NuGet; -using global::NuGet.Frameworks; +using static global::NuGet.Frameworks.FrameworkConstants.CommonFrameworks; /// /// Framework packages for net8.0. @@ -9,18 +9,182 @@ internal partial class FrameworkPackages { internal static class NETCoreApp80 { - internal static FrameworkPackages Instance { get; } = new(NuGetFramework.Parse("net8.0"), NETCoreApp70.Instance) + internal static FrameworkPackages Instance { get; } = new(Net80, FrameworkNames.NetCoreApp, NETCoreApp70.Instance) { { "System.Collections.Immutable", "8.0.0" }, { "System.Diagnostics.DiagnosticSource", "8.0.1" }, { "System.Formats.Asn1", "8.0.1" }, - { "System.Net.Http.Json", "8.0.0" }, - { "System.Reflection.Metadata", "8.0.0" }, + { "System.Net.Http.Json", "8.0.1" }, + { "System.Reflection.Metadata", "8.0.1" }, { "System.Text.Encoding.CodePages", "8.0.0" }, { "System.Text.Encodings.Web", "8.0.0" }, - { "System.Text.Json", "8.0.4" }, + { "System.Text.Json", "8.0.5" }, { "System.Threading.Channels", "8.0.0" }, { "System.Threading.Tasks.Dataflow", "8.0.1" }, }; + + internal static FrameworkPackages AspNetCore { get; } = new(Net80, FrameworkNames.AspNetCoreApp, NETCoreApp70.AspNetCore) + { + { "Microsoft.AspNetCore", "8.0.0" }, + { "Microsoft.AspNetCore.Antiforgery", "8.0.0" }, + { "Microsoft.AspNetCore.Authentication", "8.0.0" }, + { "Microsoft.AspNetCore.Authentication.Abstractions", "8.0.0" }, + { "Microsoft.AspNetCore.Authentication.BearerToken", "8.0.0" }, + { "Microsoft.AspNetCore.Authentication.Cookies", "8.0.0" }, + { "Microsoft.AspNetCore.Authentication.Core", "8.0.0" }, + { "Microsoft.AspNetCore.Authentication.OAuth", "8.0.0" }, + { "Microsoft.AspNetCore.Authorization", "8.0.0" }, + { "Microsoft.AspNetCore.Authorization.Policy", "8.0.0" }, + { "Microsoft.AspNetCore.Components", "8.0.0" }, + { "Microsoft.AspNetCore.Components.Authorization", "8.0.0" }, + { "Microsoft.AspNetCore.Components.Endpoints", "8.0.0" }, + { "Microsoft.AspNetCore.Components.Forms", "8.0.0" }, + { "Microsoft.AspNetCore.Components.Server", "8.0.0" }, + { "Microsoft.AspNetCore.Components.Web", "8.0.0" }, + { "Microsoft.AspNetCore.Connections.Abstractions", "8.0.0" }, + { "Microsoft.AspNetCore.CookiePolicy", "8.0.0" }, + { "Microsoft.AspNetCore.Cors", "8.0.0" }, + { "Microsoft.AspNetCore.Cryptography.Internal", "8.0.0" }, + { "Microsoft.AspNetCore.Cryptography.KeyDerivation", "8.0.0" }, + { "Microsoft.AspNetCore.DataProtection", "8.0.0" }, + { "Microsoft.AspNetCore.DataProtection.Abstractions", "8.0.0" }, + { "Microsoft.AspNetCore.DataProtection.Extensions", "8.0.0" }, + { "Microsoft.AspNetCore.Diagnostics", "8.0.0" }, + { "Microsoft.AspNetCore.Diagnostics.Abstractions", "8.0.0" }, + { "Microsoft.AspNetCore.Diagnostics.HealthChecks", "8.0.0" }, + { "Microsoft.AspNetCore.HostFiltering", "8.0.0" }, + { "Microsoft.AspNetCore.Hosting", "8.0.0" }, + { "Microsoft.AspNetCore.Hosting.Abstractions", "8.0.0" }, + { "Microsoft.AspNetCore.Hosting.Server.Abstractions", "8.0.0" }, + { "Microsoft.AspNetCore.Html.Abstractions", "8.0.0" }, + { "Microsoft.AspNetCore.Http", "8.0.0" }, + { "Microsoft.AspNetCore.Http.Abstractions", "8.0.0" }, + { "Microsoft.AspNetCore.Http.Connections", "8.0.0" }, + { "Microsoft.AspNetCore.Http.Connections.Common", "8.0.0" }, + { "Microsoft.AspNetCore.Http.Extensions", "8.0.0" }, + { "Microsoft.AspNetCore.Http.Features", "8.0.0" }, + { "Microsoft.AspNetCore.Http.Results", "8.0.0" }, + { "Microsoft.AspNetCore.HttpLogging", "8.0.0" }, + { "Microsoft.AspNetCore.HttpOverrides", "8.0.0" }, + { "Microsoft.AspNetCore.HttpsPolicy", "8.0.0" }, + { "Microsoft.AspNetCore.Identity", "8.0.0" }, + { "Microsoft.AspNetCore.Localization", "8.0.0" }, + { "Microsoft.AspNetCore.Localization.Routing", "8.0.0" }, + { "Microsoft.AspNetCore.Metadata", "8.0.0" }, + { "Microsoft.AspNetCore.Mvc", "8.0.0" }, + { "Microsoft.AspNetCore.Mvc.Abstractions", "8.0.0" }, + { "Microsoft.AspNetCore.Mvc.ApiExplorer", "8.0.0" }, + { "Microsoft.AspNetCore.Mvc.Core", "8.0.0" }, + { "Microsoft.AspNetCore.Mvc.Cors", "8.0.0" }, + { "Microsoft.AspNetCore.Mvc.DataAnnotations", "8.0.0" }, + { "Microsoft.AspNetCore.Mvc.Formatters.Json", "8.0.0" }, + { "Microsoft.AspNetCore.Mvc.Formatters.Xml", "8.0.0" }, + { "Microsoft.AspNetCore.Mvc.Localization", "8.0.0" }, + { "Microsoft.AspNetCore.Mvc.Razor", "8.0.0" }, + { "Microsoft.AspNetCore.Mvc.RazorPages", "8.0.0" }, + { "Microsoft.AspNetCore.Mvc.TagHelpers", "8.0.0" }, + { "Microsoft.AspNetCore.Mvc.ViewFeatures", "8.0.0" }, + { "Microsoft.AspNetCore.OutputCaching", "8.0.0" }, + { "Microsoft.AspNetCore.RateLimiting", "8.0.0" }, + { "Microsoft.AspNetCore.Razor", "8.0.0" }, + { "Microsoft.AspNetCore.Razor.Runtime", "8.0.0" }, + { "Microsoft.AspNetCore.RequestDecompression", "8.0.0" }, + { "Microsoft.AspNetCore.ResponseCaching", "8.0.0" }, + { "Microsoft.AspNetCore.ResponseCaching.Abstractions", "8.0.0" }, + { "Microsoft.AspNetCore.ResponseCompression", "8.0.0" }, + { "Microsoft.AspNetCore.Rewrite", "8.0.0" }, + { "Microsoft.AspNetCore.Routing", "8.0.0" }, + { "Microsoft.AspNetCore.Routing.Abstractions", "8.0.0" }, + { "Microsoft.AspNetCore.Server.HttpSys", "8.0.0" }, + { "Microsoft.AspNetCore.Server.IIS", "8.0.0" }, + { "Microsoft.AspNetCore.Server.IISIntegration", "8.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel", "8.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel.Core", "8.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel.Transport.NamedPipes", "8.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel.Transport.Quic", "8.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets", "8.0.0" }, + { "Microsoft.AspNetCore.Session", "8.0.0" }, + { "Microsoft.AspNetCore.SignalR", "8.0.0" }, + { "Microsoft.AspNetCore.SignalR.Common", "8.0.0" }, + { "Microsoft.AspNetCore.SignalR.Core", "8.0.0" }, + { "Microsoft.AspNetCore.SignalR.Protocols.Json", "8.0.0" }, + { "Microsoft.AspNetCore.StaticFiles", "8.0.0" }, + { "Microsoft.AspNetCore.WebSockets", "8.0.0" }, + { "Microsoft.AspNetCore.WebUtilities", "8.0.0" }, + { "Microsoft.Extensions.Caching.Abstractions", "8.0.0" }, + { "Microsoft.Extensions.Caching.Memory", "8.0.0" }, + { "Microsoft.Extensions.Configuration", "8.0.0" }, + { "Microsoft.Extensions.Configuration.Abstractions", "8.0.0" }, + { "Microsoft.Extensions.Configuration.Binder", "8.0.0" }, + { "Microsoft.Extensions.Configuration.CommandLine", "8.0.0" }, + { "Microsoft.Extensions.Configuration.EnvironmentVariables", "8.0.0" }, + { "Microsoft.Extensions.Configuration.FileExtensions", "8.0.0" }, + { "Microsoft.Extensions.Configuration.Ini", "8.0.0" }, + { "Microsoft.Extensions.Configuration.Json", "8.0.0" }, + { "Microsoft.Extensions.Configuration.KeyPerFile", "8.0.0" }, + { "Microsoft.Extensions.Configuration.UserSecrets", "8.0.0" }, + { "Microsoft.Extensions.Configuration.Xml", "8.0.0" }, + { "Microsoft.Extensions.DependencyInjection", "8.0.0" }, + { "Microsoft.Extensions.DependencyInjection.Abstractions", "8.0.0" }, + { "Microsoft.Extensions.Diagnostics", "8.0.0" }, + { "Microsoft.Extensions.Diagnostics.Abstractions", "8.0.0" }, + { "Microsoft.Extensions.Diagnostics.HealthChecks", "8.0.0" }, + { "Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions", "8.0.0" }, + { "Microsoft.Extensions.Features", "8.0.0" }, + { "Microsoft.Extensions.FileProviders.Abstractions", "8.0.0" }, + { "Microsoft.Extensions.FileProviders.Composite", "8.0.0" }, + { "Microsoft.Extensions.FileProviders.Embedded", "8.0.0" }, + { "Microsoft.Extensions.FileProviders.Physical", "8.0.0" }, + { "Microsoft.Extensions.FileSystemGlobbing", "8.0.0" }, + { "Microsoft.Extensions.Hosting", "8.0.0" }, + { "Microsoft.Extensions.Hosting.Abstractions", "8.0.0" }, + { "Microsoft.Extensions.Http", "8.0.0" }, + { "Microsoft.Extensions.Identity.Core", "8.0.0" }, + { "Microsoft.Extensions.Identity.Stores", "8.0.0" }, + { "Microsoft.Extensions.Localization", "8.0.0" }, + { "Microsoft.Extensions.Localization.Abstractions", "8.0.0" }, + { "Microsoft.Extensions.Logging", "8.0.0" }, + { "Microsoft.Extensions.Logging.Abstractions", "8.0.0" }, + { "Microsoft.Extensions.Logging.Configuration", "8.0.0" }, + { "Microsoft.Extensions.Logging.Console", "8.0.0" }, + { "Microsoft.Extensions.Logging.Debug", "8.0.0" }, + { "Microsoft.Extensions.Logging.EventLog", "8.0.0" }, + { "Microsoft.Extensions.Logging.EventSource", "8.0.0" }, + { "Microsoft.Extensions.Logging.TraceSource", "8.0.0" }, + { "Microsoft.Extensions.ObjectPool", "8.0.0" }, + { "Microsoft.Extensions.Options", "8.0.0" }, + { "Microsoft.Extensions.Options.ConfigurationExtensions", "8.0.0" }, + { "Microsoft.Extensions.Options.DataAnnotations", "8.0.0" }, + { "Microsoft.Extensions.Primitives", "8.0.0" }, + { "Microsoft.Extensions.WebEncoders", "8.0.0" }, + { "Microsoft.JSInterop", "8.0.0" }, + { "Microsoft.Net.Http.Headers", "8.0.0" }, + { "System.Diagnostics.EventLog", "8.0.0" }, + { "System.IO.Pipelines", "8.0.0" }, + { "System.Security.Cryptography.Pkcs", "8.0.0" }, + { "System.Security.Cryptography.Xml", "8.0.0" }, + { "System.Threading.RateLimiting", "8.0.0" }, + }; + + internal static FrameworkPackages WindowsDesktop { get; } = new(Net80, FrameworkNames.WindowsDesktopApp, NETCoreApp70.WindowsDesktop) + { + { "Microsoft.Win32.Registry.AccessControl", "8.0.0" }, + { "Microsoft.Win32.SystemEvents", "8.0.0" }, + { "System.CodeDom", "8.0.0" }, + { "System.Configuration.ConfigurationManager", "8.0.0" }, + { "System.Diagnostics.EventLog", "8.0.0" }, + { "System.Diagnostics.PerformanceCounter", "8.0.0" }, + { "System.Drawing.Common", "8.0.0" }, + { "System.IO.Packaging", "8.0.0" }, + { "System.Resources.Extensions", "8.0.0" }, + { "System.Security.Cryptography.Pkcs", "8.0.0" }, + { "System.Security.Cryptography.ProtectedData", "8.0.0" }, + { "System.Security.Cryptography.Xml", "8.0.0" }, + { "System.Security.Permissions", "8.0.0" }, + { "System.Threading.AccessControl", "8.0.0" }, + { "System.Windows.Extensions", "8.0.0" }, + }; + + internal static void Register() => FrameworkPackages.Register(Instance, AspNetCore, WindowsDesktop); } } diff --git a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.net9.0.cs b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.net9.0.cs index 484c7e8a3..a8e88a552 100644 --- a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.net9.0.cs +++ b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.net9.0.cs @@ -1,5 +1,6 @@ namespace Microsoft.ComponentDetection.Detectors.NuGet; +using System; using global::NuGet.Frameworks; /// @@ -9,70 +10,11 @@ internal partial class FrameworkPackages { internal static class NETCoreApp90 { - internal static FrameworkPackages Instance { get; } = new(NuGetFramework.Parse("net9.0"), NETCoreApp80.Instance) + private static NuGetFramework Net90 { get; } = new NuGetFramework(FrameworkConstants.FrameworkIdentifiers.NetCoreApp, new Version(9, 0)); + + internal static FrameworkPackages Instance { get; } = new(Net90, FrameworkNames.NetCoreApp, NETCoreApp80.Instance) { { "Microsoft.VisualBasic", "10.4.0" }, - { "runtime.debian.8-x64.runtime.native.System", "4.3.1" }, - { "runtime.debian.8-x64.runtime.native.System.IO.Compression", "4.3.2" }, - { "runtime.debian.8-x64.runtime.native.System.Net.Http", "4.3.1" }, - { "runtime.debian.8-x64.runtime.native.System.Net.Security", "4.3.1" }, - { "runtime.debian.8-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, - { "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, - { "runtime.fedora.23-x64.runtime.native.System", "4.3.1" }, - { "runtime.fedora.23-x64.runtime.native.System.IO.Compression", "4.3.2" }, - { "runtime.fedora.23-x64.runtime.native.System.Net.Http", "4.3.1" }, - { "runtime.fedora.23-x64.runtime.native.System.Net.Security", "4.3.1" }, - { "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, - { "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, - { "runtime.fedora.24-x64.runtime.native.System", "4.3.1" }, - { "runtime.fedora.24-x64.runtime.native.System.IO.Compression", "4.3.2" }, - { "runtime.fedora.24-x64.runtime.native.System.Net.Http", "4.3.1" }, - { "runtime.fedora.24-x64.runtime.native.System.Net.Security", "4.3.1" }, - { "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, - { "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, - { "runtime.opensuse.13.2-x64.runtime.native.System", "4.3.1" }, - { "runtime.opensuse.13.2-x64.runtime.native.System.IO.Compression", "4.3.2" }, - { "runtime.opensuse.13.2-x64.runtime.native.System.Net.Http", "4.3.1" }, - { "runtime.opensuse.13.2-x64.runtime.native.System.Net.Security", "4.3.1" }, - { "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, - { "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, - { "runtime.opensuse.42.1-x64.runtime.native.System", "4.3.1" }, - { "runtime.opensuse.42.1-x64.runtime.native.System.IO.Compression", "4.3.2" }, - { "runtime.opensuse.42.1-x64.runtime.native.System.Net.Http", "4.3.1" }, - { "runtime.opensuse.42.1-x64.runtime.native.System.Net.Security", "4.3.1" }, - { "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, - { "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, - { "runtime.osx.10.10-x64.runtime.native.System", "4.3.1" }, - { "runtime.osx.10.10-x64.runtime.native.System.IO.Compression", "4.3.2" }, - { "runtime.osx.10.10-x64.runtime.native.System.Net.Http", "4.3.1" }, - { "runtime.osx.10.10-x64.runtime.native.System.Net.Security", "4.3.1" }, - { "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, - { "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple", "4.3.1" }, - { "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, - { "runtime.rhel.7-x64.runtime.native.System", "4.3.1" }, - { "runtime.rhel.7-x64.runtime.native.System.IO.Compression", "4.3.2" }, - { "runtime.rhel.7-x64.runtime.native.System.Net.Http", "4.3.1" }, - { "runtime.rhel.7-x64.runtime.native.System.Net.Security", "4.3.1" }, - { "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, - { "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, - { "runtime.ubuntu.14.04-x64.runtime.native.System", "4.3.1" }, - { "runtime.ubuntu.14.04-x64.runtime.native.System.IO.Compression", "4.3.2" }, - { "runtime.ubuntu.14.04-x64.runtime.native.System.Net.Http", "4.3.1" }, - { "runtime.ubuntu.14.04-x64.runtime.native.System.Net.Security", "4.3.1" }, - { "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, - { "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, - { "runtime.ubuntu.16.04-x64.runtime.native.System", "4.3.1" }, - { "runtime.ubuntu.16.04-x64.runtime.native.System.IO.Compression", "4.3.2" }, - { "runtime.ubuntu.16.04-x64.runtime.native.System.Net.Http", "4.3.1" }, - { "runtime.ubuntu.16.04-x64.runtime.native.System.Net.Security", "4.3.1" }, - { "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, - { "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, - { "runtime.ubuntu.16.10-x64.runtime.native.System", "4.3.1" }, - { "runtime.ubuntu.16.10-x64.runtime.native.System.IO.Compression", "4.3.2" }, - { "runtime.ubuntu.16.10-x64.runtime.native.System.Net.Http", "4.3.1" }, - { "runtime.ubuntu.16.10-x64.runtime.native.System.Net.Security", "4.3.1" }, - { "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, - { "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, { "System.Buffers", "5.0.0" }, { "System.Collections.Immutable", "9.0.0" }, { "System.Diagnostics.DiagnosticSource", "9.0.0" }, @@ -94,5 +36,161 @@ internal static class NETCoreApp90 { "System.Threading.Tasks.Extensions", "5.0.0" }, { "System.Xml.XPath.XDocument", "5.0.0" }, }; + + internal static FrameworkPackages AspNetCore { get; } = new(Net90, FrameworkNames.AspNetCoreApp, NETCoreApp80.AspNetCore) + { + { "Microsoft.AspNetCore", "9.0.0" }, + { "Microsoft.AspNetCore.Antiforgery", "9.0.0" }, + { "Microsoft.AspNetCore.Authentication", "9.0.0" }, + { "Microsoft.AspNetCore.Authentication.Abstractions", "9.0.0" }, + { "Microsoft.AspNetCore.Authentication.BearerToken", "9.0.0" }, + { "Microsoft.AspNetCore.Authentication.Cookies", "9.0.0" }, + { "Microsoft.AspNetCore.Authentication.Core", "9.0.0" }, + { "Microsoft.AspNetCore.Authentication.OAuth", "9.0.0" }, + { "Microsoft.AspNetCore.Authorization", "9.0.0" }, + { "Microsoft.AspNetCore.Authorization.Policy", "9.0.0" }, + { "Microsoft.AspNetCore.Components", "9.0.0" }, + { "Microsoft.AspNetCore.Components.Authorization", "9.0.0" }, + { "Microsoft.AspNetCore.Components.Endpoints", "9.0.0" }, + { "Microsoft.AspNetCore.Components.Forms", "9.0.0" }, + { "Microsoft.AspNetCore.Components.Server", "9.0.0" }, + { "Microsoft.AspNetCore.Components.Web", "9.0.0" }, + { "Microsoft.AspNetCore.Connections.Abstractions", "9.0.0" }, + { "Microsoft.AspNetCore.CookiePolicy", "9.0.0" }, + { "Microsoft.AspNetCore.Cors", "9.0.0" }, + { "Microsoft.AspNetCore.Cryptography.Internal", "9.0.0" }, + { "Microsoft.AspNetCore.Cryptography.KeyDerivation", "9.0.0" }, + { "Microsoft.AspNetCore.DataProtection", "9.0.0" }, + { "Microsoft.AspNetCore.DataProtection.Abstractions", "9.0.0" }, + { "Microsoft.AspNetCore.DataProtection.Extensions", "9.0.0" }, + { "Microsoft.AspNetCore.Diagnostics", "9.0.0" }, + { "Microsoft.AspNetCore.Diagnostics.Abstractions", "9.0.0" }, + { "Microsoft.AspNetCore.Diagnostics.HealthChecks", "9.0.0" }, + { "Microsoft.AspNetCore.HostFiltering", "9.0.0" }, + { "Microsoft.AspNetCore.Hosting", "9.0.0" }, + { "Microsoft.AspNetCore.Hosting.Abstractions", "9.0.0" }, + { "Microsoft.AspNetCore.Hosting.Server.Abstractions", "9.0.0" }, + { "Microsoft.AspNetCore.Html.Abstractions", "9.0.0" }, + { "Microsoft.AspNetCore.Http", "9.0.0" }, + { "Microsoft.AspNetCore.Http.Abstractions", "9.0.0" }, + { "Microsoft.AspNetCore.Http.Connections", "9.0.0" }, + { "Microsoft.AspNetCore.Http.Connections.Common", "9.0.0" }, + { "Microsoft.AspNetCore.Http.Extensions", "9.0.0" }, + { "Microsoft.AspNetCore.Http.Features", "9.0.0" }, + { "Microsoft.AspNetCore.Http.Results", "9.0.0" }, + { "Microsoft.AspNetCore.HttpLogging", "9.0.0" }, + { "Microsoft.AspNetCore.HttpOverrides", "9.0.0" }, + { "Microsoft.AspNetCore.HttpsPolicy", "9.0.0" }, + { "Microsoft.AspNetCore.Identity", "9.0.0" }, + { "Microsoft.AspNetCore.Localization", "9.0.0" }, + { "Microsoft.AspNetCore.Localization.Routing", "9.0.0" }, + { "Microsoft.AspNetCore.Metadata", "9.0.0" }, + { "Microsoft.AspNetCore.Mvc", "9.0.0" }, + { "Microsoft.AspNetCore.Mvc.Abstractions", "9.0.0" }, + { "Microsoft.AspNetCore.Mvc.ApiExplorer", "9.0.0" }, + { "Microsoft.AspNetCore.Mvc.Core", "9.0.0" }, + { "Microsoft.AspNetCore.Mvc.Cors", "9.0.0" }, + { "Microsoft.AspNetCore.Mvc.DataAnnotations", "9.0.0" }, + { "Microsoft.AspNetCore.Mvc.Formatters.Json", "9.0.0" }, + { "Microsoft.AspNetCore.Mvc.Formatters.Xml", "9.0.0" }, + { "Microsoft.AspNetCore.Mvc.Localization", "9.0.0" }, + { "Microsoft.AspNetCore.Mvc.Razor", "9.0.0" }, + { "Microsoft.AspNetCore.Mvc.RazorPages", "9.0.0" }, + { "Microsoft.AspNetCore.Mvc.TagHelpers", "9.0.0" }, + { "Microsoft.AspNetCore.Mvc.ViewFeatures", "9.0.0" }, + { "Microsoft.AspNetCore.OutputCaching", "9.0.0" }, + { "Microsoft.AspNetCore.RateLimiting", "9.0.0" }, + { "Microsoft.AspNetCore.Razor", "9.0.0" }, + { "Microsoft.AspNetCore.Razor.Runtime", "9.0.0" }, + { "Microsoft.AspNetCore.RequestDecompression", "9.0.0" }, + { "Microsoft.AspNetCore.ResponseCaching", "9.0.0" }, + { "Microsoft.AspNetCore.ResponseCaching.Abstractions", "9.0.0" }, + { "Microsoft.AspNetCore.ResponseCompression", "9.0.0" }, + { "Microsoft.AspNetCore.Rewrite", "9.0.0" }, + { "Microsoft.AspNetCore.Routing", "9.0.0" }, + { "Microsoft.AspNetCore.Routing.Abstractions", "9.0.0" }, + { "Microsoft.AspNetCore.Server.HttpSys", "9.0.0" }, + { "Microsoft.AspNetCore.Server.IIS", "9.0.0" }, + { "Microsoft.AspNetCore.Server.IISIntegration", "9.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel", "9.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel.Core", "9.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel.Transport.NamedPipes", "9.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel.Transport.Quic", "9.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets", "9.0.0" }, + { "Microsoft.AspNetCore.Session", "9.0.0" }, + { "Microsoft.AspNetCore.SignalR", "9.0.0" }, + { "Microsoft.AspNetCore.SignalR.Common", "9.0.0" }, + { "Microsoft.AspNetCore.SignalR.Core", "9.0.0" }, + { "Microsoft.AspNetCore.SignalR.Protocols.Json", "9.0.0" }, + { "Microsoft.AspNetCore.StaticAssets", "9.0.0" }, + { "Microsoft.AspNetCore.StaticFiles", "9.0.0" }, + { "Microsoft.AspNetCore.WebSockets", "9.0.0" }, + { "Microsoft.AspNetCore.WebUtilities", "9.0.0" }, + { "Microsoft.Extensions.Caching.Abstractions", "9.0.0" }, + { "Microsoft.Extensions.Caching.Memory", "9.0.0" }, + { "Microsoft.Extensions.Configuration", "9.0.0" }, + { "Microsoft.Extensions.Configuration.Abstractions", "9.0.0" }, + { "Microsoft.Extensions.Configuration.Binder", "9.0.0" }, + { "Microsoft.Extensions.Configuration.CommandLine", "9.0.0" }, + { "Microsoft.Extensions.Configuration.EnvironmentVariables", "9.0.0" }, + { "Microsoft.Extensions.Configuration.FileExtensions", "9.0.0" }, + { "Microsoft.Extensions.Configuration.Ini", "9.0.0" }, + { "Microsoft.Extensions.Configuration.Json", "9.0.0" }, + { "Microsoft.Extensions.Configuration.KeyPerFile", "9.0.0" }, + { "Microsoft.Extensions.Configuration.UserSecrets", "9.0.0" }, + { "Microsoft.Extensions.Configuration.Xml", "9.0.0" }, + { "Microsoft.Extensions.DependencyInjection", "9.0.0" }, + { "Microsoft.Extensions.DependencyInjection.Abstractions", "9.0.0" }, + { "Microsoft.Extensions.Diagnostics", "9.0.0" }, + { "Microsoft.Extensions.Diagnostics.Abstractions", "9.0.0" }, + { "Microsoft.Extensions.Diagnostics.HealthChecks", "9.0.0" }, + { "Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions", "9.0.0" }, + { "Microsoft.Extensions.Features", "9.0.0" }, + { "Microsoft.Extensions.FileProviders.Abstractions", "9.0.0" }, + { "Microsoft.Extensions.FileProviders.Composite", "9.0.0" }, + { "Microsoft.Extensions.FileProviders.Embedded", "9.0.0" }, + { "Microsoft.Extensions.FileProviders.Physical", "9.0.0" }, + { "Microsoft.Extensions.FileSystemGlobbing", "9.0.0" }, + { "Microsoft.Extensions.Hosting", "9.0.0" }, + { "Microsoft.Extensions.Hosting.Abstractions", "9.0.0" }, + { "Microsoft.Extensions.Http", "9.0.0" }, + { "Microsoft.Extensions.Identity.Core", "9.0.0" }, + { "Microsoft.Extensions.Identity.Stores", "9.0.0" }, + { "Microsoft.Extensions.Localization", "9.0.0" }, + { "Microsoft.Extensions.Localization.Abstractions", "9.0.0" }, + { "Microsoft.Extensions.Logging", "9.0.0" }, + { "Microsoft.Extensions.Logging.Abstractions", "9.0.0" }, + { "Microsoft.Extensions.Logging.Configuration", "9.0.0" }, + { "Microsoft.Extensions.Logging.Console", "9.0.0" }, + { "Microsoft.Extensions.Logging.Debug", "9.0.0" }, + { "Microsoft.Extensions.Logging.EventLog", "9.0.0" }, + { "Microsoft.Extensions.Logging.EventSource", "9.0.0" }, + { "Microsoft.Extensions.Logging.TraceSource", "9.0.0" }, + { "Microsoft.Extensions.ObjectPool", "9.0.0" }, + { "Microsoft.Extensions.Options", "9.0.0" }, + { "Microsoft.Extensions.Options.ConfigurationExtensions", "9.0.0" }, + { "Microsoft.Extensions.Options.DataAnnotations", "9.0.0" }, + { "Microsoft.Extensions.Primitives", "9.0.0" }, + { "Microsoft.Extensions.WebEncoders", "9.0.0" }, + { "Microsoft.JSInterop", "9.0.0" }, + { "Microsoft.Net.Http.Headers", "9.0.0" }, + { "System.Diagnostics.EventLog", "9.0.0" }, + { "System.Security.Cryptography.Pkcs", "8.0.1" }, + { "System.Security.Cryptography.Xml", "9.0.0" }, + { "System.Threading.RateLimiting", "9.0.0" }, + }; + + internal static FrameworkPackages WindowsDesktop { get; } = new(Net90, FrameworkNames.WindowsDesktopApp, NETCoreApp80.WindowsDesktop) + { + { "System.Configuration.ConfigurationManager", "8.0.1" }, + { "System.Diagnostics.EventLog", "8.0.1" }, + { "System.Diagnostics.PerformanceCounter", "8.0.1" }, + { "System.Drawing.Common", "8.0.10" }, + { "System.IO.Packaging", "8.0.1" }, + { "System.Security.Cryptography.Pkcs", "8.0.1" }, + { "System.Security.Cryptography.Xml", "8.0.2" }, + }; + + internal static void Register() => FrameworkPackages.Register(Instance, AspNetCore, WindowsDesktop); } } diff --git a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp2.0.cs b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp2.0.cs index dc934febf..fb029dcfe 100644 --- a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp2.0.cs +++ b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp2.0.cs @@ -1,6 +1,6 @@ namespace Microsoft.ComponentDetection.Detectors.NuGet; -using global::NuGet.Frameworks; +using static global::NuGet.Frameworks.FrameworkConstants.CommonFrameworks; /// /// Framework packages for .NETCoreApp,Version=v2.0. @@ -9,8 +9,162 @@ internal partial class FrameworkPackages { internal static class NETCoreApp20 { - internal static FrameworkPackages Instance { get; } = new(NuGetFramework.Parse("netcoreapp2.0"), NETStandard20.Instance) + internal static FrameworkPackages Instance { get; } = new(NetCoreApp20, FrameworkNames.NetCoreApp, NETStandard20.Instance) { + { "Microsoft.CSharp", "4.4.0" }, + { "Microsoft.VisualBasic", "10.2.0" }, + { "Microsoft.Win32.Registry", "4.4.0" }, + { "runtime.any.System.Collections", "4.3.0" }, + { "runtime.any.System.Diagnostics.Tools", "4.3.0" }, + { "runtime.any.System.Diagnostics.Tracing", "4.3.0" }, + { "runtime.any.System.Globalization", "4.3.0" }, + { "runtime.any.System.Globalization.Calendars", "4.3.0" }, + { "runtime.any.System.IO", "4.3.0" }, + { "runtime.any.System.Reflection", "4.3.0" }, + { "runtime.any.System.Reflection.Extensions", "4.3.0" }, + { "runtime.any.System.Reflection.Primitives", "4.3.0" }, + { "runtime.any.System.Resources.ResourceManager", "4.3.0" }, + { "runtime.any.System.Runtime", "4.3.1" }, + { "runtime.any.System.Runtime.Handles", "4.3.0" }, + { "runtime.any.System.Runtime.InteropServices", "4.3.0" }, + { "runtime.any.System.Text.Encoding", "4.3.0" }, + { "runtime.any.System.Text.Encoding.Extensions", "4.3.0" }, + { "runtime.any.System.Threading.Tasks", "4.3.0" }, + { "runtime.any.System.Threading.Timer", "4.3.0" }, + { "runtime.aot.System.Collections", "4.3.0" }, + { "runtime.aot.System.Diagnostics.Tools", "4.3.0" }, + { "runtime.aot.System.Diagnostics.Tracing", "4.3.0" }, + { "runtime.aot.System.Globalization", "4.3.0" }, + { "runtime.aot.System.Globalization.Calendars", "4.3.0" }, + { "runtime.aot.System.IO", "4.3.0" }, + { "runtime.aot.System.Reflection", "4.3.0" }, + { "runtime.aot.System.Reflection.Extensions", "4.3.0" }, + { "runtime.aot.System.Reflection.Primitives", "4.3.0" }, + { "runtime.aot.System.Resources.ResourceManager", "4.3.0" }, + { "runtime.aot.System.Runtime", "4.3.1" }, + { "runtime.aot.System.Runtime.Handles", "4.3.0" }, + { "runtime.aot.System.Runtime.InteropServices", "4.3.0" }, + { "runtime.aot.System.Text.Encoding", "4.3.0" }, + { "runtime.aot.System.Text.Encoding.Extensions", "4.3.0" }, + { "runtime.aot.System.Threading.Tasks", "4.3.0" }, + { "runtime.aot.System.Threading.Timer", "4.3.0" }, + { "runtime.debian.8-x64.runtime.native.System", "4.3.1" }, + { "runtime.debian.8-x64.runtime.native.System.IO.Compression", "4.3.2" }, + { "runtime.debian.8-x64.runtime.native.System.Net.Http", "4.3.1" }, + { "runtime.debian.8-x64.runtime.native.System.Net.Security", "4.3.1" }, + { "runtime.debian.8-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, + { "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, + { "runtime.debian.9-x64.runtime.native.System", "4.3.1" }, + { "runtime.debian.9-x64.runtime.native.System.IO.Compression", "4.3.2" }, + { "runtime.debian.9-x64.runtime.native.System.Net.Http", "4.3.1" }, + { "runtime.debian.9-x64.runtime.native.System.Net.Security", "4.3.1" }, + { "runtime.debian.9-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, + { "runtime.debian.9-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, + { "runtime.fedora.23-x64.runtime.native.System", "4.3.1" }, + { "runtime.fedora.23-x64.runtime.native.System.IO.Compression", "4.3.2" }, + { "runtime.fedora.23-x64.runtime.native.System.Net.Http", "4.3.1" }, + { "runtime.fedora.23-x64.runtime.native.System.Net.Security", "4.3.1" }, + { "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, + { "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, + { "runtime.fedora.24-x64.runtime.native.System", "4.3.1" }, + { "runtime.fedora.24-x64.runtime.native.System.IO.Compression", "4.3.2" }, + { "runtime.fedora.24-x64.runtime.native.System.Net.Http", "4.3.1" }, + { "runtime.fedora.24-x64.runtime.native.System.Net.Security", "4.3.1" }, + { "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, + { "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, + { "runtime.fedora.27-x64.runtime.native.System", "4.3.1" }, + { "runtime.fedora.27-x64.runtime.native.System.IO.Compression", "4.3.2" }, + { "runtime.fedora.27-x64.runtime.native.System.Net.Http", "4.3.1" }, + { "runtime.fedora.27-x64.runtime.native.System.Net.Security", "4.3.1" }, + { "runtime.fedora.27-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, + { "runtime.fedora.27-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, + { "runtime.fedora.28-x64.runtime.native.System", "4.3.1" }, + { "runtime.fedora.28-x64.runtime.native.System.IO.Compression", "4.3.2" }, + { "runtime.fedora.28-x64.runtime.native.System.Net.Http", "4.3.1" }, + { "runtime.fedora.28-x64.runtime.native.System.Net.Security", "4.3.1" }, + { "runtime.fedora.28-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, + { "runtime.fedora.28-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, + { "runtime.native.System.Security.Cryptography", "4.3.4" }, + { "runtime.native.System.Security.Cryptography.Apple", "4.3.1" }, + { "runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, + { "runtime.opensuse.13.2-x64.runtime.native.System", "4.3.1" }, + { "runtime.opensuse.13.2-x64.runtime.native.System.IO.Compression", "4.3.2" }, + { "runtime.opensuse.13.2-x64.runtime.native.System.Net.Http", "4.3.1" }, + { "runtime.opensuse.13.2-x64.runtime.native.System.Net.Security", "4.3.1" }, + { "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, + { "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, + { "runtime.opensuse.42.1-x64.runtime.native.System", "4.3.1" }, + { "runtime.opensuse.42.1-x64.runtime.native.System.IO.Compression", "4.3.2" }, + { "runtime.opensuse.42.1-x64.runtime.native.System.Net.Http", "4.3.1" }, + { "runtime.opensuse.42.1-x64.runtime.native.System.Net.Security", "4.3.1" }, + { "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, + { "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, + { "runtime.opensuse.42.3-x64.runtime.native.System", "4.3.1" }, + { "runtime.opensuse.42.3-x64.runtime.native.System.IO.Compression", "4.3.2" }, + { "runtime.opensuse.42.3-x64.runtime.native.System.Net.Http", "4.3.1" }, + { "runtime.opensuse.42.3-x64.runtime.native.System.Net.Security", "4.3.1" }, + { "runtime.opensuse.42.3-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, + { "runtime.opensuse.42.3-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, + { "runtime.osx.10.10-x64.runtime.native.System", "4.3.1" }, + { "runtime.osx.10.10-x64.runtime.native.System.IO.Compression", "4.3.2" }, + { "runtime.osx.10.10-x64.runtime.native.System.Net.Http", "4.3.1" }, + { "runtime.osx.10.10-x64.runtime.native.System.Net.Security", "4.3.1" }, + { "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, + { "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple", "4.3.1" }, + { "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, + { "runtime.rhel.7-x64.runtime.native.System", "4.3.1" }, + { "runtime.rhel.7-x64.runtime.native.System.IO.Compression", "4.3.2" }, + { "runtime.rhel.7-x64.runtime.native.System.Net.Http", "4.3.1" }, + { "runtime.rhel.7-x64.runtime.native.System.Net.Security", "4.3.1" }, + { "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, + { "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, + { "runtime.ubuntu.14.04-x64.runtime.native.System", "4.3.1" }, + { "runtime.ubuntu.14.04-x64.runtime.native.System.IO.Compression", "4.3.2" }, + { "runtime.ubuntu.14.04-x64.runtime.native.System.Net.Http", "4.3.1" }, + { "runtime.ubuntu.14.04-x64.runtime.native.System.Net.Security", "4.3.1" }, + { "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, + { "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, + { "runtime.ubuntu.16.04-x64.runtime.native.System", "4.3.1" }, + { "runtime.ubuntu.16.04-x64.runtime.native.System.IO.Compression", "4.3.2" }, + { "runtime.ubuntu.16.04-x64.runtime.native.System.Net.Http", "4.3.1" }, + { "runtime.ubuntu.16.04-x64.runtime.native.System.Net.Security", "4.3.1" }, + { "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, + { "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, + { "runtime.ubuntu.16.10-x64.runtime.native.System", "4.3.1" }, + { "runtime.ubuntu.16.10-x64.runtime.native.System.IO.Compression", "4.3.2" }, + { "runtime.ubuntu.16.10-x64.runtime.native.System.Net.Http", "4.3.1" }, + { "runtime.ubuntu.16.10-x64.runtime.native.System.Net.Security", "4.3.1" }, + { "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, + { "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, + { "runtime.ubuntu.18.04-x64.runtime.native.System", "4.3.1" }, + { "runtime.ubuntu.18.04-x64.runtime.native.System.IO.Compression", "4.3.2" }, + { "runtime.ubuntu.18.04-x64.runtime.native.System.Net.Http", "4.3.1" }, + { "runtime.ubuntu.18.04-x64.runtime.native.System.Net.Security", "4.3.1" }, + { "runtime.ubuntu.18.04-x64.runtime.native.System.Security.Cryptography", "4.3.4" }, + { "runtime.ubuntu.18.04-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.3" }, + { "runtime.unix.Microsoft.Win32.Primitives", "4.3.0" }, + { "runtime.unix.System.Console", "4.3.1" }, + { "runtime.unix.System.Diagnostics.Debug", "4.3.0" }, + { "runtime.unix.System.IO.FileSystem", "4.3.0" }, + { "runtime.unix.System.Net.Primitives", "4.3.0" }, + { "runtime.unix.System.Net.Sockets", "4.3.0" }, + { "runtime.unix.System.Private.Uri", "4.3.1" }, + { "runtime.unix.System.Runtime.Extensions", "4.3.1" }, + { "runtime.win.Microsoft.Win32.Primitives", "4.3.0" }, + { "runtime.win.System.Console", "4.3.1" }, + { "runtime.win.System.Diagnostics.Debug", "4.3.0" }, + { "runtime.win.System.IO.FileSystem", "4.3.0" }, + { "runtime.win.System.Net.Primitives", "4.3.0" }, + { "runtime.win.System.Net.Sockets", "4.3.0" }, + { "runtime.win.System.Runtime.Extensions", "4.3.1" }, + { "runtime.win10-arm-aot.runtime.native.System.IO.Compression", "4.0.1" }, + { "runtime.win10-arm64.runtime.native.System.IO.Compression", "4.3.2" }, + { "runtime.win10-x64-aot.runtime.native.System.IO.Compression", "4.0.1" }, + { "runtime.win10-x86-aot.runtime.native.System.IO.Compression", "4.0.1" }, + { "runtime.win7-x64.runtime.native.System.IO.Compression", "4.3.2" }, + { "runtime.win7-x86.runtime.native.System.IO.Compression", "4.3.2" }, + { "runtime.win7.System.Private.Uri", "4.3.1" }, + { "runtime.win8-arm.runtime.native.System.IO.Compression", "4.3.2" }, { "System.Buffers", "4.4.0" }, { "System.Collections.Concurrent", "4.3.0" }, { "System.Collections.Immutable", "1.4.0" }, @@ -20,12 +174,14 @@ internal static class NETCoreApp20 { "System.Diagnostics.Contracts", "4.3.0" }, { "System.Diagnostics.DiagnosticSource", "4.4.1" }, { "System.Dynamic.Runtime", "4.3.0" }, + { "System.IO.FileSystem.AccessControl", "4.4.0" }, { "System.Linq.Parallel", "4.3.0" }, { "System.Linq.Queryable", "4.3.0" }, { "System.Net.Requests", "4.3.0" }, { "System.Net.WebHeaderCollection", "4.3.0" }, { "System.Numerics.Vectors", "4.4.0" }, { "System.ObjectModel", "4.3.0" }, + { "System.Private.DataContractSerialization", "4.3.0" }, { "System.Reflection.DispatchProxy", "4.4.0" }, { "System.Reflection.Emit", "4.7.0" }, { "System.Reflection.Emit.ILGeneration", "4.7.0" }, @@ -36,7 +192,11 @@ internal static class NETCoreApp20 { "System.Runtime.Loader", "4.3.0" }, { "System.Runtime.Numerics", "4.3.0" }, { "System.Runtime.Serialization.Json", "4.3.0" }, + { "System.Security.AccessControl", "4.4.0" }, + { "System.Security.Cryptography.Cng", "4.4.0" }, + { "System.Security.Cryptography.OpenSsl", "4.4.0" }, { "System.Security.Principal", "4.3.0" }, + { "System.Security.Principal.Windows", "4.4.0" }, { "System.Text.RegularExpressions", "4.3.1" }, { "System.Threading", "4.3.0" }, { "System.Threading.Tasks.Dataflow", "4.8.0" }, @@ -45,5 +205,7 @@ internal static class NETCoreApp20 { "System.Xml.XDocument", "4.3.0" }, { "System.Xml.XmlSerializer", "4.3.0" }, }; + + internal static void Register() => FrameworkPackages.Register(Instance); } } diff --git a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp2.1.cs b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp2.1.cs index ef5489f50..bd36be6d7 100644 --- a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp2.1.cs +++ b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp2.1.cs @@ -1,6 +1,6 @@ namespace Microsoft.ComponentDetection.Detectors.NuGet; -using global::NuGet.Frameworks; +using static global::NuGet.Frameworks.FrameworkConstants.CommonFrameworks; /// /// Framework packages for .NETCoreApp,Version=v2.1. @@ -9,17 +9,30 @@ internal partial class FrameworkPackages { internal static class NETCoreApp21 { - internal static FrameworkPackages Instance { get; } = new(NuGetFramework.Parse("netcoreapp2.1"), NETCoreApp20.Instance) + internal static FrameworkPackages Instance { get; } = new(NetCoreApp21, FrameworkNames.NetCoreApp, NETCoreApp20.Instance) { + { "Microsoft.CSharp", "4.5.0" }, + { "Microsoft.VisualBasic", "10.3.0" }, + { "Microsoft.Win32.Registry", "4.5.0" }, + { "System.Buffers", "4.5.0" }, { "System.Collections.Immutable", "1.5.0" }, - { "System.ComponentModel.Annotations", "4.4.1" }, + { "System.ComponentModel.Annotations", "4.5.0" }, { "System.Diagnostics.DiagnosticSource", "4.5.0" }, + { "System.IO.FileSystem.AccessControl", "4.5.0" }, + { "System.IO.Pipes.AccessControl", "4.5.0" }, { "System.Memory", "4.5.5" }, + { "System.Numerics.Vectors", "4.5.0" }, { "System.Reflection.DispatchProxy", "4.5.0" }, { "System.Reflection.Metadata", "1.6.0" }, + { "System.Security.AccessControl", "4.5.0" }, + { "System.Security.Cryptography.Cng", "4.5.2" }, + { "System.Security.Cryptography.OpenSsl", "4.5.0" }, + { "System.Security.Principal.Windows", "4.5.0" }, { "System.Threading.Tasks.Dataflow", "4.9.0" }, { "System.Threading.Tasks.Extensions", "4.5.4" }, { "System.ValueTuple", "4.5.0" }, }; + + internal static void Register() => FrameworkPackages.Register(Instance); } } diff --git a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp2.2.cs b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp2.2.cs index d9fa440fa..a3a28741f 100644 --- a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp2.2.cs +++ b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp2.2.cs @@ -1,6 +1,6 @@ namespace Microsoft.ComponentDetection.Detectors.NuGet; -using global::NuGet.Frameworks; +using static global::NuGet.Frameworks.FrameworkConstants.CommonFrameworks; /// /// Framework packages for .NETCoreApp,Version=v2.2. @@ -10,6 +10,8 @@ internal partial class FrameworkPackages internal static class NETCoreApp22 { // .NETCore 2.2 was the same as .NETCore 2.1 - internal static FrameworkPackages Instance { get; } = new(NuGetFramework.Parse("netcoreapp2.2"), NETCoreApp21.Instance); + internal static FrameworkPackages Instance { get; } = new(NetCoreApp22, FrameworkNames.NetCoreApp, NETCoreApp21.Instance); + + internal static void Register() => FrameworkPackages.Register(Instance); } } diff --git a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp3.0.cs b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp3.0.cs index 84f3c854d..079a9a0cd 100644 --- a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp3.0.cs +++ b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp3.0.cs @@ -1,6 +1,6 @@ namespace Microsoft.ComponentDetection.Detectors.NuGet; -using global::NuGet.Frameworks; +using static global::NuGet.Frameworks.FrameworkConstants.CommonFrameworks; /// /// Framework packages for .NETCoreApp,Version=v3.0. @@ -9,41 +9,189 @@ internal partial class FrameworkPackages { internal static class NETCoreApp30 { - internal static FrameworkPackages Instance { get; } = new(NuGetFramework.Parse("netcoreapp3.0"), NETCoreApp21.Instance) + internal static FrameworkPackages Instance { get; } = new(NetCoreApp30, FrameworkNames.NetCoreApp, NETCoreApp21.Instance) { - { "Microsoft.CSharp", "4.4.0" }, - { "Microsoft.Win32.Registry", "4.4.0" }, - { "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.0" }, - { "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.0" }, - { "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.0" }, - { "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.0" }, - { "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.0" }, - { "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple", "4.3.0" }, - { "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.0" }, - { "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.0" }, - { "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.0" }, - { "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.0" }, - { "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl", "4.3.0" }, + { "Microsoft.CSharp", "4.6.0" }, + { "Microsoft.Win32.Registry", "4.6.0" }, + { "System.Buffers", "4.5.1" }, { "System.Collections.Immutable", "1.6.0" }, { "System.ComponentModel.Annotations", "4.6.0" }, { "System.Data.DataSetExtensions", "4.5.0" }, { "System.Diagnostics.DiagnosticSource", "4.6.0" }, - { "System.IO.FileSystem.AccessControl", "4.4.0" }, - { "System.Numerics.Vectors", "4.5.0" }, - { "System.Private.DataContractSerialization", "4.3.0" }, + { "System.IO.FileSystem.AccessControl", "4.6.0" }, + { "System.IO.Pipes.AccessControl", "4.6.0" }, { "System.Reflection.DispatchProxy", "4.6.0" }, { "System.Reflection.Metadata", "1.7.0" }, { "System.Runtime.CompilerServices.Unsafe", "4.6.0" }, - { "System.Security.AccessControl", "4.4.0" }, - { "System.Security.Cryptography.Cng", "4.4.0" }, - { "System.Security.Cryptography.OpenSsl", "4.4.0" }, + { "System.Runtime.WindowsRuntime", "4.6.0" }, + { "System.Runtime.WindowsRuntime.UI.Xaml", "4.6.0" }, + { "System.Security.AccessControl", "4.6.0" }, + { "System.Security.Cryptography.Cng", "4.6.0" }, + { "System.Security.Cryptography.OpenSsl", "4.6.0" }, { "System.Security.Cryptography.Xml", "4.4.0" }, - { "System.Security.Principal.Windows", "4.4.0" }, + { "System.Security.Principal.Windows", "4.6.0" }, { "System.Text.Encoding.CodePages", "4.6.0" }, { "System.Text.Encodings.Web", "4.6.0" }, { "System.Text.Json", "4.6.0" }, { "System.Threading.Channels", "4.6.0" }, { "System.Threading.Tasks.Dataflow", "4.10.0" }, }; + + internal static FrameworkPackages AspNetCore { get; } = new(NetCoreApp30, FrameworkNames.AspNetCoreApp) + { + { "Microsoft.AspNetCore", "3.0.0" }, + { "Microsoft.AspNetCore.Antiforgery", "3.0.0" }, + { "Microsoft.AspNetCore.Authentication", "3.0.0" }, + { "Microsoft.AspNetCore.Authentication.Abstractions", "3.0.0" }, + { "Microsoft.AspNetCore.Authentication.Cookies", "3.0.0" }, + { "Microsoft.AspNetCore.Authentication.Core", "3.0.0" }, + { "Microsoft.AspNetCore.Authentication.OAuth", "3.0.0" }, + { "Microsoft.AspNetCore.Authorization", "3.0.0" }, + { "Microsoft.AspNetCore.Authorization.Policy", "3.0.0" }, + { "Microsoft.AspNetCore.Components", "3.0.0" }, + { "Microsoft.AspNetCore.Components.Authorization", "3.0.0" }, + { "Microsoft.AspNetCore.Components.Forms", "3.0.0" }, + { "Microsoft.AspNetCore.Components.Server", "3.0.0" }, + { "Microsoft.AspNetCore.Components.Web", "3.0.0" }, + { "Microsoft.AspNetCore.Connections.Abstractions", "3.0.0" }, + { "Microsoft.AspNetCore.CookiePolicy", "3.0.0" }, + { "Microsoft.AspNetCore.Cors", "3.0.0" }, + { "Microsoft.AspNetCore.Cryptography.Internal", "3.0.0" }, + { "Microsoft.AspNetCore.Cryptography.KeyDerivation", "3.0.0" }, + { "Microsoft.AspNetCore.DataProtection", "3.0.0" }, + { "Microsoft.AspNetCore.DataProtection.Abstractions", "3.0.0" }, + { "Microsoft.AspNetCore.DataProtection.Extensions", "3.0.0" }, + { "Microsoft.AspNetCore.Diagnostics", "3.0.0" }, + { "Microsoft.AspNetCore.Diagnostics.Abstractions", "3.0.0" }, + { "Microsoft.AspNetCore.Diagnostics.HealthChecks", "3.0.0" }, + { "Microsoft.AspNetCore.HostFiltering", "3.0.0" }, + { "Microsoft.AspNetCore.Hosting", "3.0.0" }, + { "Microsoft.AspNetCore.Hosting.Abstractions", "3.0.0" }, + { "Microsoft.AspNetCore.Hosting.Server.Abstractions", "3.0.0" }, + { "Microsoft.AspNetCore.Html.Abstractions", "3.0.0" }, + { "Microsoft.AspNetCore.Http", "3.0.0" }, + { "Microsoft.AspNetCore.Http.Abstractions", "3.0.0" }, + { "Microsoft.AspNetCore.Http.Connections", "3.0.0" }, + { "Microsoft.AspNetCore.Http.Connections.Common", "3.0.0" }, + { "Microsoft.AspNetCore.Http.Extensions", "3.0.0" }, + { "Microsoft.AspNetCore.Http.Features", "3.0.0" }, + { "Microsoft.AspNetCore.HttpOverrides", "3.0.0" }, + { "Microsoft.AspNetCore.HttpsPolicy", "3.0.0" }, + { "Microsoft.AspNetCore.Identity", "3.0.0" }, + { "Microsoft.AspNetCore.Localization", "3.0.0" }, + { "Microsoft.AspNetCore.Localization.Routing", "3.0.0" }, + { "Microsoft.AspNetCore.Metadata", "3.0.0" }, + { "Microsoft.AspNetCore.Mvc", "3.0.0" }, + { "Microsoft.AspNetCore.Mvc.Abstractions", "3.0.0" }, + { "Microsoft.AspNetCore.Mvc.ApiExplorer", "3.0.0" }, + { "Microsoft.AspNetCore.Mvc.Core", "3.0.0" }, + { "Microsoft.AspNetCore.Mvc.Cors", "3.0.0" }, + { "Microsoft.AspNetCore.Mvc.DataAnnotations", "3.0.0" }, + { "Microsoft.AspNetCore.Mvc.Formatters.Json", "3.0.0" }, + { "Microsoft.AspNetCore.Mvc.Formatters.Xml", "3.0.0" }, + { "Microsoft.AspNetCore.Mvc.Localization", "3.0.0" }, + { "Microsoft.AspNetCore.Mvc.Razor", "3.0.0" }, + { "Microsoft.AspNetCore.Mvc.RazorPages", "3.0.0" }, + { "Microsoft.AspNetCore.Mvc.TagHelpers", "3.0.0" }, + { "Microsoft.AspNetCore.Mvc.ViewFeatures", "3.0.0" }, + { "Microsoft.AspNetCore.Razor", "3.0.0" }, + { "Microsoft.AspNetCore.Razor.Runtime", "3.0.0" }, + { "Microsoft.AspNetCore.ResponseCaching", "3.0.0" }, + { "Microsoft.AspNetCore.ResponseCaching.Abstractions", "3.0.0" }, + { "Microsoft.AspNetCore.ResponseCompression", "3.0.0" }, + { "Microsoft.AspNetCore.Rewrite", "3.0.0" }, + { "Microsoft.AspNetCore.Routing", "3.0.0" }, + { "Microsoft.AspNetCore.Routing.Abstractions", "3.0.0" }, + { "Microsoft.AspNetCore.Server.HttpSys", "3.0.0" }, + { "Microsoft.AspNetCore.Server.IIS", "3.0.0" }, + { "Microsoft.AspNetCore.Server.IISIntegration", "3.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel", "3.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel.Core", "3.0.0" }, + { "Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets", "3.0.0" }, + { "Microsoft.AspNetCore.Session", "3.0.0" }, + { "Microsoft.AspNetCore.SignalR", "3.0.0" }, + { "Microsoft.AspNetCore.SignalR.Common", "3.0.0" }, + { "Microsoft.AspNetCore.SignalR.Core", "3.0.0" }, + { "Microsoft.AspNetCore.SignalR.Protocols.Json", "3.0.0" }, + { "Microsoft.AspNetCore.StaticFiles", "3.0.0" }, + { "Microsoft.AspNetCore.WebSockets", "3.0.0" }, + { "Microsoft.AspNetCore.WebUtilities", "3.0.0" }, + { "Microsoft.Extensions.Caching.Abstractions", "3.0.0" }, + { "Microsoft.Extensions.Caching.Memory", "3.0.0" }, + { "Microsoft.Extensions.Configuration", "3.0.0" }, + { "Microsoft.Extensions.Configuration.Abstractions", "3.0.0" }, + { "Microsoft.Extensions.Configuration.Binder", "3.0.0" }, + { "Microsoft.Extensions.Configuration.CommandLine", "3.0.0" }, + { "Microsoft.Extensions.Configuration.EnvironmentVariables", "3.0.0" }, + { "Microsoft.Extensions.Configuration.FileExtensions", "3.0.0" }, + { "Microsoft.Extensions.Configuration.Ini", "3.0.0" }, + { "Microsoft.Extensions.Configuration.Json", "3.0.0" }, + { "Microsoft.Extensions.Configuration.KeyPerFile", "3.0.0" }, + { "Microsoft.Extensions.Configuration.UserSecrets", "3.0.0" }, + { "Microsoft.Extensions.Configuration.Xml", "3.0.0" }, + { "Microsoft.Extensions.DependencyInjection", "3.0.0" }, + { "Microsoft.Extensions.DependencyInjection.Abstractions", "3.0.0" }, + { "Microsoft.Extensions.Diagnostics.HealthChecks", "3.0.0" }, + { "Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions", "3.0.0" }, + { "Microsoft.Extensions.FileProviders.Abstractions", "3.0.0" }, + { "Microsoft.Extensions.FileProviders.Composite", "3.0.0" }, + { "Microsoft.Extensions.FileProviders.Embedded", "3.0.0" }, + { "Microsoft.Extensions.FileProviders.Physical", "3.0.0" }, + { "Microsoft.Extensions.FileSystemGlobbing", "3.0.0" }, + { "Microsoft.Extensions.Hosting", "3.0.0" }, + { "Microsoft.Extensions.Hosting.Abstractions", "3.0.0" }, + { "Microsoft.Extensions.Http", "3.0.0" }, + { "Microsoft.Extensions.Identity.Core", "3.0.0" }, + { "Microsoft.Extensions.Identity.Stores", "3.0.0" }, + { "Microsoft.Extensions.Localization", "3.0.0" }, + { "Microsoft.Extensions.Localization.Abstractions", "3.0.0" }, + { "Microsoft.Extensions.Logging", "3.0.0" }, + { "Microsoft.Extensions.Logging.Abstractions", "3.0.0" }, + { "Microsoft.Extensions.Logging.Configuration", "3.0.0" }, + { "Microsoft.Extensions.Logging.Console", "3.0.0" }, + { "Microsoft.Extensions.Logging.Debug", "3.0.0" }, + { "Microsoft.Extensions.Logging.EventLog", "3.0.0" }, + { "Microsoft.Extensions.Logging.EventSource", "3.0.0" }, + { "Microsoft.Extensions.Logging.TraceSource", "3.0.0" }, + { "Microsoft.Extensions.ObjectPool", "3.0.0" }, + { "Microsoft.Extensions.Options", "3.0.0" }, + { "Microsoft.Extensions.Options.ConfigurationExtensions", "3.0.0" }, + { "Microsoft.Extensions.Options.DataAnnotations", "3.0.0" }, + { "Microsoft.Extensions.Primitives", "3.0.0" }, + { "Microsoft.Extensions.WebEncoders", "3.0.0" }, + { "Microsoft.JSInterop", "3.0.0" }, + { "Microsoft.Net.Http.Headers", "3.0.0" }, + { "Microsoft.Win32.Registry", "4.6.0" }, + { "System.Diagnostics.EventLog", "4.6.0" }, + { "System.IO.Pipelines", "4.6.0" }, + { "System.Security.AccessControl", "4.6.0" }, + { "System.Security.Cryptography.Cng", "4.6.0" }, + { "System.Security.Cryptography.Xml", "4.6.0" }, + { "System.Security.Permissions", "4.6.0" }, + { "System.Security.Principal.Windows", "4.6.0" }, + { "System.Windows.Extensions", "4.6.0" }, + }; + + internal static FrameworkPackages WindowsDesktop { get; } = new(NetCoreApp30, FrameworkNames.WindowsDesktopApp) + { + { "Microsoft.Win32.Registry.AccessControl", "4.6.0" }, + { "Microsoft.Win32.SystemEvents", "4.6.0" }, + { "System.CodeDom", "4.6.0" }, + { "System.Configuration.ConfigurationManager", "4.6.0" }, + { "System.Diagnostics.EventLog", "4.6.0" }, + { "System.Diagnostics.PerformanceCounter", "4.5.0" }, + { "System.DirectoryServices", "4.6.0" }, + { "System.Drawing.Common", "4.7.3" }, + { "System.IO.Packaging", "4.6.0" }, + { "System.Resources.Extensions", "4.6.0" }, + { "System.Security.Cryptography.Pkcs", "4.6.0" }, + { "System.Security.Cryptography.ProtectedData", "4.6.0" }, + { "System.Security.Cryptography.Xml", "4.6.0" }, + { "System.Security.Permissions", "4.6.0" }, + { "System.Threading.AccessControl", "4.6.0" }, + { "System.Windows.Extensions", "4.6.0" }, + }; + + internal static void Register() => FrameworkPackages.Register(Instance, AspNetCore, WindowsDesktop); } } diff --git a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp3.1.cs b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp3.1.cs index f7f879843..ce3338d80 100644 --- a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp3.1.cs +++ b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp3.1.cs @@ -1,6 +1,6 @@ namespace Microsoft.ComponentDetection.Detectors.NuGet; -using global::NuGet.Frameworks; +using static global::NuGet.Frameworks.FrameworkConstants.CommonFrameworks; /// /// Framework packages for .NETCoreApp,Version=v3.1. @@ -9,19 +9,186 @@ internal partial class FrameworkPackages { internal static class NETCoreApp31 { - internal static FrameworkPackages Instance { get; } = new(NuGetFramework.Parse("netcoreapp3.1"), NETCoreApp30.Instance) + internal static FrameworkPackages Instance { get; } = new(NetCoreApp31, FrameworkNames.NetCoreApp, NETCoreApp30.Instance) { + { "Microsoft.CSharp", "4.7.0" }, + { "Microsoft.Win32.Registry", "4.7.0" }, { "System.Collections.Immutable", "1.7.0" }, { "System.ComponentModel.Annotations", "4.7.0" }, { "System.Diagnostics.DiagnosticSource", "4.7.0" }, + { "System.IO.FileSystem.AccessControl", "4.7.0" }, { "System.Reflection.DispatchProxy", "4.7.0" }, { "System.Reflection.Metadata", "1.8.0" }, { "System.Runtime.CompilerServices.Unsafe", "4.7.1" }, + { "System.Runtime.WindowsRuntime", "4.7.0" }, + { "System.Runtime.WindowsRuntime.UI.Xaml", "4.7.0" }, + { "System.Security.AccessControl", "4.7.0" }, + { "System.Security.Cryptography.OpenSsl", "4.7.0" }, + { "System.Security.Principal.Windows", "4.7.0" }, { "System.Text.Encoding.CodePages", "4.7.0" }, { "System.Text.Encodings.Web", "4.7.0" }, { "System.Text.Json", "4.7.0" }, { "System.Threading.Channels", "4.7.0" }, { "System.Threading.Tasks.Dataflow", "4.11.0" }, }; + + internal static FrameworkPackages AspNetCore { get; } = new(NetCoreApp31, FrameworkNames.AspNetCoreApp, NETCoreApp30.AspNetCore) + { + { "Microsoft.AspNetCore", "3.1.0" }, + { "Microsoft.AspNetCore.Antiforgery", "3.1.0" }, + { "Microsoft.AspNetCore.Authentication", "3.1.0" }, + { "Microsoft.AspNetCore.Authentication.Abstractions", "3.1.0" }, + { "Microsoft.AspNetCore.Authentication.Cookies", "3.1.0" }, + { "Microsoft.AspNetCore.Authentication.Core", "3.1.0" }, + { "Microsoft.AspNetCore.Authentication.OAuth", "3.1.0" }, + { "Microsoft.AspNetCore.Authorization", "3.1.0" }, + { "Microsoft.AspNetCore.Authorization.Policy", "3.1.0" }, + { "Microsoft.AspNetCore.Components", "3.1.0" }, + { "Microsoft.AspNetCore.Components.Authorization", "3.1.0" }, + { "Microsoft.AspNetCore.Components.Forms", "3.1.0" }, + { "Microsoft.AspNetCore.Components.Server", "3.1.0" }, + { "Microsoft.AspNetCore.Components.Web", "3.1.0" }, + { "Microsoft.AspNetCore.Connections.Abstractions", "3.1.0" }, + { "Microsoft.AspNetCore.CookiePolicy", "3.1.0" }, + { "Microsoft.AspNetCore.Cors", "3.1.0" }, + { "Microsoft.AspNetCore.Cryptography.Internal", "3.1.0" }, + { "Microsoft.AspNetCore.Cryptography.KeyDerivation", "3.1.0" }, + { "Microsoft.AspNetCore.DataProtection", "3.1.0" }, + { "Microsoft.AspNetCore.DataProtection.Abstractions", "3.1.0" }, + { "Microsoft.AspNetCore.DataProtection.Extensions", "3.1.0" }, + { "Microsoft.AspNetCore.Diagnostics", "3.1.0" }, + { "Microsoft.AspNetCore.Diagnostics.Abstractions", "3.1.0" }, + { "Microsoft.AspNetCore.Diagnostics.HealthChecks", "3.1.0" }, + { "Microsoft.AspNetCore.HostFiltering", "3.1.0" }, + { "Microsoft.AspNetCore.Hosting", "3.1.0" }, + { "Microsoft.AspNetCore.Hosting.Abstractions", "3.1.0" }, + { "Microsoft.AspNetCore.Hosting.Server.Abstractions", "3.1.0" }, + { "Microsoft.AspNetCore.Html.Abstractions", "3.1.0" }, + { "Microsoft.AspNetCore.Http", "3.1.0" }, + { "Microsoft.AspNetCore.Http.Abstractions", "3.1.0" }, + { "Microsoft.AspNetCore.Http.Connections", "3.1.0" }, + { "Microsoft.AspNetCore.Http.Connections.Common", "3.1.0" }, + { "Microsoft.AspNetCore.Http.Extensions", "3.1.0" }, + { "Microsoft.AspNetCore.Http.Features", "3.1.0" }, + { "Microsoft.AspNetCore.HttpOverrides", "3.1.0" }, + { "Microsoft.AspNetCore.HttpsPolicy", "3.1.0" }, + { "Microsoft.AspNetCore.Identity", "3.1.0" }, + { "Microsoft.AspNetCore.Localization", "3.1.0" }, + { "Microsoft.AspNetCore.Localization.Routing", "3.1.0" }, + { "Microsoft.AspNetCore.Metadata", "3.1.0" }, + { "Microsoft.AspNetCore.Mvc", "3.1.0" }, + { "Microsoft.AspNetCore.Mvc.Abstractions", "3.1.0" }, + { "Microsoft.AspNetCore.Mvc.ApiExplorer", "3.1.0" }, + { "Microsoft.AspNetCore.Mvc.Core", "3.1.0" }, + { "Microsoft.AspNetCore.Mvc.Cors", "3.1.0" }, + { "Microsoft.AspNetCore.Mvc.DataAnnotations", "3.1.0" }, + { "Microsoft.AspNetCore.Mvc.Formatters.Json", "3.1.0" }, + { "Microsoft.AspNetCore.Mvc.Formatters.Xml", "3.1.0" }, + { "Microsoft.AspNetCore.Mvc.Localization", "3.1.0" }, + { "Microsoft.AspNetCore.Mvc.Razor", "3.1.0" }, + { "Microsoft.AspNetCore.Mvc.RazorPages", "3.1.0" }, + { "Microsoft.AspNetCore.Mvc.TagHelpers", "3.1.0" }, + { "Microsoft.AspNetCore.Mvc.ViewFeatures", "3.1.0" }, + { "Microsoft.AspNetCore.Razor", "3.1.0" }, + { "Microsoft.AspNetCore.Razor.Runtime", "3.1.0" }, + { "Microsoft.AspNetCore.ResponseCaching", "3.1.0" }, + { "Microsoft.AspNetCore.ResponseCaching.Abstractions", "3.1.0" }, + { "Microsoft.AspNetCore.ResponseCompression", "3.1.0" }, + { "Microsoft.AspNetCore.Rewrite", "3.1.0" }, + { "Microsoft.AspNetCore.Routing", "3.1.0" }, + { "Microsoft.AspNetCore.Routing.Abstractions", "3.1.0" }, + { "Microsoft.AspNetCore.Server.HttpSys", "3.1.0" }, + { "Microsoft.AspNetCore.Server.IIS", "3.1.0" }, + { "Microsoft.AspNetCore.Server.IISIntegration", "3.1.0" }, + { "Microsoft.AspNetCore.Server.Kestrel", "3.1.0" }, + { "Microsoft.AspNetCore.Server.Kestrel.Core", "3.1.0" }, + { "Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets", "3.1.0" }, + { "Microsoft.AspNetCore.Session", "3.1.0" }, + { "Microsoft.AspNetCore.SignalR", "3.1.0" }, + { "Microsoft.AspNetCore.SignalR.Common", "3.1.0" }, + { "Microsoft.AspNetCore.SignalR.Core", "3.1.0" }, + { "Microsoft.AspNetCore.SignalR.Protocols.Json", "3.1.0" }, + { "Microsoft.AspNetCore.StaticFiles", "3.1.0" }, + { "Microsoft.AspNetCore.WebSockets", "3.1.0" }, + { "Microsoft.AspNetCore.WebUtilities", "3.1.0" }, + { "Microsoft.Extensions.Caching.Abstractions", "3.1.0" }, + { "Microsoft.Extensions.Caching.Memory", "3.1.0" }, + { "Microsoft.Extensions.Configuration", "3.1.0" }, + { "Microsoft.Extensions.Configuration.Abstractions", "3.1.0" }, + { "Microsoft.Extensions.Configuration.Binder", "3.1.0" }, + { "Microsoft.Extensions.Configuration.CommandLine", "3.1.0" }, + { "Microsoft.Extensions.Configuration.EnvironmentVariables", "3.1.0" }, + { "Microsoft.Extensions.Configuration.FileExtensions", "3.1.0" }, + { "Microsoft.Extensions.Configuration.Ini", "3.1.0" }, + { "Microsoft.Extensions.Configuration.Json", "3.1.0" }, + { "Microsoft.Extensions.Configuration.KeyPerFile", "3.1.0" }, + { "Microsoft.Extensions.Configuration.UserSecrets", "3.1.0" }, + { "Microsoft.Extensions.Configuration.Xml", "3.1.0" }, + { "Microsoft.Extensions.DependencyInjection", "3.1.0" }, + { "Microsoft.Extensions.DependencyInjection.Abstractions", "3.1.0" }, + { "Microsoft.Extensions.Diagnostics.HealthChecks", "3.1.0" }, + { "Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions", "3.1.0" }, + { "Microsoft.Extensions.FileProviders.Abstractions", "3.1.0" }, + { "Microsoft.Extensions.FileProviders.Composite", "3.1.0" }, + { "Microsoft.Extensions.FileProviders.Embedded", "3.1.0" }, + { "Microsoft.Extensions.FileProviders.Physical", "3.1.0" }, + { "Microsoft.Extensions.FileSystemGlobbing", "3.1.0" }, + { "Microsoft.Extensions.Hosting", "3.1.0" }, + { "Microsoft.Extensions.Hosting.Abstractions", "3.1.0" }, + { "Microsoft.Extensions.Http", "3.1.0" }, + { "Microsoft.Extensions.Identity.Core", "3.1.0" }, + { "Microsoft.Extensions.Identity.Stores", "3.1.0" }, + { "Microsoft.Extensions.Localization", "3.1.0" }, + { "Microsoft.Extensions.Localization.Abstractions", "3.1.0" }, + { "Microsoft.Extensions.Logging", "3.1.0" }, + { "Microsoft.Extensions.Logging.Abstractions", "3.1.0" }, + { "Microsoft.Extensions.Logging.Configuration", "3.1.0" }, + { "Microsoft.Extensions.Logging.Console", "3.1.0" }, + { "Microsoft.Extensions.Logging.Debug", "3.1.0" }, + { "Microsoft.Extensions.Logging.EventLog", "3.1.0" }, + { "Microsoft.Extensions.Logging.EventSource", "3.1.0" }, + { "Microsoft.Extensions.Logging.TraceSource", "3.1.0" }, + { "Microsoft.Extensions.ObjectPool", "3.1.0" }, + { "Microsoft.Extensions.Options", "3.1.0" }, + { "Microsoft.Extensions.Options.ConfigurationExtensions", "3.1.0" }, + { "Microsoft.Extensions.Options.DataAnnotations", "3.1.0" }, + { "Microsoft.Extensions.Primitives", "3.1.0" }, + { "Microsoft.Extensions.WebEncoders", "3.1.0" }, + { "Microsoft.JSInterop", "3.1.0" }, + { "Microsoft.Net.Http.Headers", "3.1.0" }, + { "Microsoft.Win32.Registry", "4.7.0" }, + { "Microsoft.Win32.SystemEvents", "4.7.0" }, + { "System.Diagnostics.EventLog", "4.7.0" }, + { "System.Drawing.Common", "4.7.3" }, + { "System.IO.Pipelines", "4.7.0" }, + { "System.Security.AccessControl", "4.7.0" }, + { "System.Security.Cryptography.Cng", "4.7.0" }, + { "System.Security.Cryptography.Pkcs", "4.7.0" }, + { "System.Security.Cryptography.Xml", "4.7.0" }, + { "System.Security.Permissions", "4.7.0" }, + { "System.Security.Principal.Windows", "4.7.0" }, + { "System.Windows.Extensions", "4.7.0" }, + }; + + internal static FrameworkPackages WindowsDesktop { get; } = new(NetCoreApp31, FrameworkNames.WindowsDesktopApp, NETCoreApp30.WindowsDesktop) + { + { "Microsoft.Win32.Registry.AccessControl", "4.7.0" }, + { "Microsoft.Win32.SystemEvents", "4.7.0" }, + { "System.CodeDom", "4.7.0" }, + { "System.Configuration.ConfigurationManager", "4.7.0" }, + { "System.Diagnostics.EventLog", "4.7.0" }, + { "System.Diagnostics.PerformanceCounter", "4.7.0" }, + { "System.DirectoryServices", "8.0.0" }, + { "System.IO.Packaging", "4.7.0" }, + { "System.Resources.Extensions", "4.7.0" }, + { "System.Security.Cryptography.Pkcs", "4.7.0" }, + { "System.Security.Cryptography.ProtectedData", "4.7.0" }, + { "System.Security.Cryptography.Xml", "4.7.0" }, + { "System.Security.Permissions", "4.7.0" }, + { "System.Threading.AccessControl", "4.7.0" }, + { "System.Windows.Extensions", "4.7.0" }, + }; + + internal static void Register() => FrameworkPackages.Register(Instance, AspNetCore, WindowsDesktop); } } diff --git a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netstandard2.0.cs b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netstandard2.0.cs index 8095fb527..66c9bdd64 100644 --- a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netstandard2.0.cs +++ b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netstandard2.0.cs @@ -1,6 +1,6 @@ namespace Microsoft.ComponentDetection.Detectors.NuGet; -using global::NuGet.Frameworks; +using static global::NuGet.Frameworks.FrameworkConstants.CommonFrameworks; /// /// Framework packages for .NETStandard,Version=v2.0. @@ -9,7 +9,7 @@ internal partial class FrameworkPackages { internal static class NETStandard20 { - internal static FrameworkPackages Instance { get; } = new(NuGetFramework.Parse("netstandard2.0")) + internal static FrameworkPackages Instance { get; } = new(NetStandard20, FrameworkNames.NetStandardLibrary) { { "Microsoft.Win32.Primitives", "4.3.0" }, { "System.AppContext", "4.3.0" }, @@ -104,5 +104,7 @@ internal static class NETStandard20 { "System.Xml.XPath", "4.3.0" }, { "System.Xml.XPath.XDocument", "4.3.0" }, }; + + internal static void Register() => FrameworkPackages.Register(Instance); } } diff --git a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netstandard2.1.cs b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netstandard2.1.cs index 9d5b2bc00..5b6aeb282 100644 --- a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netstandard2.1.cs +++ b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netstandard2.1.cs @@ -1,6 +1,6 @@ namespace Microsoft.ComponentDetection.Detectors.NuGet; -using global::NuGet.Frameworks; +using static global::NuGet.Frameworks.FrameworkConstants.CommonFrameworks; /// /// Framework packages for .NETStandard,Version=v2.1. @@ -9,7 +9,7 @@ internal partial class FrameworkPackages { internal static class NETStandard21 { - internal static FrameworkPackages Instance { get; } = new(NuGetFramework.Parse("netstandard2.1"), NETStandard20.Instance) + internal static FrameworkPackages Instance { get; } = new(NetStandard21, FrameworkNames.NetStandardLibrary, NETStandard20.Instance) { { "System.Buffers", "4.5.1" }, { "System.Collections.Concurrent", "4.3.0" }, @@ -44,5 +44,7 @@ internal static class NETStandard21 { "System.Xml.XDocument", "4.3.0" }, { "System.Xml.XmlSerializer", "4.3.0" }, }; + + internal static void Register() => FrameworkPackages.Register(Instance); } } diff --git a/src/Microsoft.ComponentDetection.Detectors/nuget/NuGetPackageReferenceFrameworkAwareDetector.cs b/src/Microsoft.ComponentDetection.Detectors/nuget/NuGetPackageReferenceFrameworkAwareDetector.cs index 628d997f9..41b23a4b3 100644 --- a/src/Microsoft.ComponentDetection.Detectors/nuget/NuGetPackageReferenceFrameworkAwareDetector.cs +++ b/src/Microsoft.ComponentDetection.Detectors/nuget/NuGetPackageReferenceFrameworkAwareDetector.cs @@ -44,6 +44,24 @@ public NuGetPackageReferenceFrameworkAwareDetector( public override int Version { get; } = 1; + private static string[] GetFrameworkReferences(LockFile lockFile, LockFileTarget target) + { + var frameworkInformation = lockFile.PackageSpec.TargetFrameworks.FirstOrDefault(x => x.FrameworkName.Equals(target.TargetFramework)); + + if (frameworkInformation == null) + { + return []; + } + + // add directly referenced frameworks + var results = frameworkInformation.FrameworkReferences.Select(x => x.Name); + + // add transitive framework references + results = results.Concat(target.Libraries.SelectMany(l => l.FrameworkReferences)); + + return results.Distinct().ToArray(); + } + protected override Task OnFileFoundAsync(ProcessRequest processRequest, IDictionary detectorArgs, CancellationToken cancellationToken = default) { try @@ -69,13 +87,15 @@ protected override Task OnFileFoundAsync(ProcessRequest processRequest, IDiction var singleFileComponentRecorder = this.ComponentRecorder.CreateSingleFileComponentRecorder(lockFile.PackageSpec.RestoreMetadata.ProjectPath); foreach (var target in lockFile.Targets) { - var frameworkPackages = FrameworkPackages.GetFrameworkPackages(target.TargetFramework); + var frameworkReferences = GetFrameworkReferences(lockFile, target); + var frameworkPackages = FrameworkPackages.GetFrameworkPackages(target.TargetFramework, frameworkReferences); + bool IsAFrameworkPackage(string id, NuGetVersion version) => frameworkPackages.Any(fp => fp.IsAFrameworkComponent(id, version)); // This call to GetTargetLibrary is not guarded, because if this can't be resolved then something is fundamentally broken (e.g. an explicit dependency reference not being in the list of libraries) // issue: we treat top level dependencies for all targets as top level for each target, but some may not be top level for other targets, or may not even be present for other targets. foreach (var library in explicitReferencedDependencies.Select(x => target.GetTargetLibrary(x.Name)).Where(x => x != null)) { - this.NavigateAndRegister(target, explicitlyReferencedComponentIds, singleFileComponentRecorder, library, null, frameworkPackages); + this.NavigateAndRegister(target, explicitlyReferencedComponentIds, singleFileComponentRecorder, library, null, IsAFrameworkPackage); } } @@ -97,7 +117,7 @@ private void NavigateAndRegister( ISingleFileComponentRecorder singleFileComponentRecorder, LockFileTargetLibrary library, string parentComponentId, - FrameworkPackages frameworkPackages, + Func isAFrameworkComponent, HashSet visited = null) { if (library.Type == ProjectDependencyType) @@ -105,7 +125,7 @@ private void NavigateAndRegister( return; } - var isFrameworkComponent = frameworkPackages?.IsAFrameworkComponent(library.Name, library.Version) ?? false; + var isFrameworkComponent = isAFrameworkComponent(library.Name, library.Version); var isDevelopmentDependency = IsADevelopmentDependency(library); visited ??= []; @@ -133,7 +153,7 @@ private void NavigateAndRegister( if (targetLibrary != null) { visited.Add(dependency.Id); - this.NavigateAndRegister(target, explicitlyReferencedComponentIds, singleFileComponentRecorder, targetLibrary, libraryComponent.Component.Id, frameworkPackages, visited); + this.NavigateAndRegister(target, explicitlyReferencedComponentIds, singleFileComponentRecorder, targetLibrary, libraryComponent.Component.Id, isAFrameworkComponent, visited); } } diff --git a/test/Microsoft.ComponentDetection.Detectors.Tests/Mocks/TestResources.Designer.cs b/test/Microsoft.ComponentDetection.Detectors.Tests/Mocks/TestResources.Designer.cs index 38496cb38..dac121c0c 100644 --- a/test/Microsoft.ComponentDetection.Detectors.Tests/Mocks/TestResources.Designer.cs +++ b/test/Microsoft.ComponentDetection.Detectors.Tests/Mocks/TestResources.Designer.cs @@ -1,342 +1,440 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Microsoft.ComponentDetection.Detectors.Tests.Mocks { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class TestResources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal TestResources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.ComponentDetection.Detectors.Tests.Mocks.TestResources", typeof(TestResources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized string similar to integrationTestCompileClasspath - Compile classpath for source set 'integration test'. - ///+--- commons-io:commons-io:2.5 - ///+--- org.kohsuke:github-api:1.94 - ///| +--- org.apache.commons:commons-lang3:3.7 - ///| +--- commons-codec:commons-codec:1.7 - ///| +--- com.fasterxml.jackson.core:jackson-databind:2.9.2 - ///| | +--- com.fasterxml.jackson.core:jackson-annotations:2.9.0 - ///| | \--- com.fasterxml.jackson.core:jackson-core:2.9.2 - ///| \--- commons-io:commons-io:1.4 -> 2.5 - ///+--- org.zeroturnaround:zt-zip: [rest of string was truncated]";. - /// - internal static string GradlewDependencyOutput { - get { - return ResourceManager.GetString("GradlewDependencyOutput", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to org.apache.maven:maven-compat:jar:3.6.1-SNAPSHOT - ///+- org.apache.maven:maven-model:jar:3.6.1-SNAPSHOT:compile - ///+- org.apache.maven:maven-model-builder:jar:3.6.1-SNAPSHOT:compile - ///| \- org.apache.maven:maven-builder-support:jar:3.6.1-SNAPSHOT:compile - ///+- org.apache.maven:maven-settings:jar:3.6.1-SNAPSHOT:compile - ///+- org.apache.maven:maven-settings-builder:jar:3.6.1-SNAPSHOT:compile - ///| \- org.sonatype.plexus:plexus-sec-dispatcher:jar:1.4:compile - ///| \- org.sonatype.plexus:plexus-cipher:jar:1.7:compile - ///+- [rest of string was truncated]";. - /// - internal static string MvnCliDependencyOutput { - get { - return ResourceManager.GetString("MvnCliDependencyOutput", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to { - /// "version": "1", - /// "pip_version": "24.0", - /// "install": [ - /// { - /// "download_info": { - /// "url": "https://files.pythonhosted.org/packages/72/c3/532326adbb2b76f709e3e582aeefd0a85bd7454599ff450d90dd9540f5ed/jupyterlab-4.2.0-py3-none-any.whl", - /// "archive_info": { - /// "hash": "sha256=0dfe9278e25a145362289c555d9beb505697d269c10e99909766af7c440ad3cc", - /// "hashes": { - /// "sha256": "0dfe9278e25a145362289c555d9beb505697d269c10e99909766af7c440ad3cc" - /// } - /// [rest of string was truncated]";. - /// - internal static string pip_report_jupyterlab { - get { - return ResourceManager.GetString("pip_report_jupyterlab", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to { - /// "version": "1", - /// "pip_version": "24.0", - /// "install": [ - /// { - /// "download_info": { - /// "url": "https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl", - /// "archive_info": { - /// "hash": "sha256=8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254", - /// "hashes": { - /// "sha256": "8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" - /// } - /// } - /// [rest of string was truncated]";. - /// - internal static string pip_report_multi_pkg { - get { - return ResourceManager.GetString("pip_report_multi_pkg", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to { - /// "version": "1", - /// "pip_version": "24.0", - /// "install": [ - /// { - /// "download_info": { - /// "url": "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl", - /// "archive_info": { - /// "hash": "sha256=70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6", - /// "hashes": { - /// "sha256": "70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6" - /// } - /// } [rest of string was truncated]";. - /// - internal static string pip_report_simple_extras { - get { - return ResourceManager.GetString("pip_report_simple_extras", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to { - /// "version": "1", - /// "pip_version": "24.0", - /// "install": [ - /// { - /// "download_info": { - /// "url": "https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl", - /// "archive_info": { - /// "hash": "sha256=8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254", - /// "hashes": { - /// "sha256": "8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" - /// } - /// } - /// [rest of string was truncated]";. - /// - internal static string pip_report_single_pkg { - get { - return ResourceManager.GetString("pip_report_single_pkg", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to { - /// "version": "2", - /// "pip_version": "24.0", - /// "install": [ - /// { - /// "download_info": { - /// "url": "https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl", - /// "archive_info": { - /// "hash": "sha256=8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254", - /// "hashes": { - /// "sha256": "8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" - /// } - /// } - /// [rest of string was truncated]";. - /// - internal static string pip_report_single_pkg_bad_version { - get { - return ResourceManager.GetString("pip_report_single_pkg_bad_version", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to { - /// "version": "1", - /// "pip_version": "24.0", - /// "install": [ - /// { - /// "download_info": { - /// "url": "https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl", - /// "archive_info": { - /// "hash": "sha256=8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254", - /// "hashes": { - /// "sha256": "8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" - /// } - /// } - /// [rest of string was truncated]";. - /// - internal static string pip_report_single_pkg_invalid_pkg_version - { - get - { - return ResourceManager.GetString("pip_report_single_pkg_invalid_pkg_version", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to { - /// "version": 3, - /// "targets": { - /// ".NETCoreApp,Version=v2.2": { - /// "CommandLineParser/2.8.0": { - /// "type": "package", - /// "compile": { - /// "lib/netstandard2.0/_._": {} - /// }, - /// "runtime": { - /// "lib/netstandard2.0/CommandLine.dll": {} - /// } - /// }, - /// "coverlet.msbuild/2.5.1": { - /// "type": "package", - /// "build": { - /// "build/netstandard2.0/coverlet.msbuild.props": {}, - /// "build/netstandard2.0/coverlet.msbuild.targets": {} - /// } - /// }, - /// "DotNet.Glob/2.1.1": { - /// "type": "package [rest of string was truncated]";. - /// - internal static string project_assets_2_2 { - get { - return ResourceManager.GetString("project_assets_2_2", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to { - /// "version": 3, - /// "targets": { - /// ".NETCoreApp,Version=v2.2": { - /// "coverlet.msbuild/2.5.1": { - /// "type": "package", - /// "build": { - /// "build/netstandard2.0/coverlet.msbuild.props": {}, - /// "build/netstandard2.0/coverlet.msbuild.targets": {} - /// } - /// }, - /// "DotNet.Glob/2.1.1": { - /// "type": "package", - /// "dependencies": { - /// "NETStandard.Library": "1.6.1" - /// }, - /// "compile": { - /// "lib/netstandard1.1/DotNet.Glob.dll": {} - /// }, - /// "runtime": { - /// "lib/netstandard1.1/DotNet.Glob.dll": {} - /// [rest of string was truncated]";. - /// - internal static string project_assets_2_2_additional { - get { - return ResourceManager.GetString("project_assets_2_2_additional", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to { - /// "version": 3, - /// "targets": { - /// ".NETCoreApp,Version=v3.1": { - /// "Microsoft.Extensions.DependencyModel/3.0.0": { - /// "type": "package", - /// "dependencies": { - /// "System.Text.Json": "4.6.0" - /// }, - /// "compile": { - /// "lib/netstandard2.0/Microsoft.Extensions.DependencyModel.dll": {} - /// }, - /// "runtime": { - /// "lib/netstandard2.0/Microsoft.Extensions.DependencyModel.dll": {} - /// } - /// }, - /// "Microsoft. [rest of string was truncated]";. - /// - internal static string project_assets_3_1 { - get { - return ResourceManager.GetString("project_assets_3_1", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to { - /// "version": 3, - /// "targets": { - /// ".NETFramework,Version=v4.7.2": {}, - /// "net8.0": {} - /// }, - /// "libraries": {}, - /// "projectFileDependencyGroups": { - /// ".NETFramework,Version=v4.7.2": [], - /// "net8.0": [] - /// }, - /// "packageFolders": { - /// "C:\\Users\\username\\.nuget\\packages\\": {}, - /// "C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages": {} - /// }, - /// "project": { - /// "version": "1.0.0", - /// "restore": { - /// "projectUniqueName": "C:\\src\\packageDownloadSample\\package [rest of string was truncated]";. - /// - internal static string project_assets_packageDownload { - get { - return ResourceManager.GetString("project_assets_packageDownload", resourceCulture); - } - } - } -} +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Microsoft.ComponentDetection.Detectors.Tests.Mocks { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class TestResources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal TestResources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.ComponentDetection.Detectors.Tests.Mocks.TestResources", typeof(TestResources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to integrationTestCompileClasspath - Compile classpath for source set 'integration test'. + ///+--- commons-io:commons-io:2.5 + ///+--- org.kohsuke:github-api:1.94 + ///| +--- org.apache.commons:commons-lang3:3.7 + ///| +--- commons-codec:commons-codec:1.7 + ///| +--- com.fasterxml.jackson.core:jackson-databind:2.9.2 + ///| | +--- com.fasterxml.jackson.core:jackson-annotations:2.9.0 + ///| | \--- com.fasterxml.jackson.core:jackson-core:2.9.2 + ///| \--- commons-io:commons-io:1.4 -> 2.5 + ///+--- org.zeroturnaround:zt-zip: [rest of string was truncated]";. + /// + internal static string GradlewDependencyOutput { + get { + return ResourceManager.GetString("GradlewDependencyOutput", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to org.apache.maven:maven-compat:jar:3.6.1-SNAPSHOT + ///+- org.apache.maven:maven-model:jar:3.6.1-SNAPSHOT:compile + ///+- org.apache.maven:maven-model-builder:jar:3.6.1-SNAPSHOT:compile + ///| \- org.apache.maven:maven-builder-support:jar:3.6.1-SNAPSHOT:compile + ///+- org.apache.maven:maven-settings:jar:3.6.1-SNAPSHOT:compile + ///+- org.apache.maven:maven-settings-builder:jar:3.6.1-SNAPSHOT:compile + ///| \- org.sonatype.plexus:plexus-sec-dispatcher:jar:1.4:compile + ///| \- org.sonatype.plexus:plexus-cipher:jar:1.7:compile + ///+- [rest of string was truncated]";. + /// + internal static string MvnCliDependencyOutput { + get { + return ResourceManager.GetString("MvnCliDependencyOutput", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to { + /// "version": "1", + /// "pip_version": "24.0", + /// "install": [ + /// { + /// "download_info": { + /// "url": "https://files.pythonhosted.org/packages/72/c3/532326adbb2b76f709e3e582aeefd0a85bd7454599ff450d90dd9540f5ed/jupyterlab-4.2.0-py3-none-any.whl", + /// "archive_info": { + /// "hash": "sha256=0dfe9278e25a145362289c555d9beb505697d269c10e99909766af7c440ad3cc", + /// "hashes": { + /// "sha256": "0dfe9278e25a145362289c555d9beb505697d269c10e99909766af7c440ad3cc" + /// } + /// [rest of string was truncated]";. + /// + internal static string pip_report_jupyterlab { + get { + return ResourceManager.GetString("pip_report_jupyterlab", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to { + /// "version": "1", + /// "pip_version": "24.0", + /// "install": [ + /// { + /// "download_info": { + /// "url": "https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl", + /// "archive_info": { + /// "hash": "sha256=8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254", + /// "hashes": { + /// "sha256": "8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" + /// } + /// } /// [rest of string was truncated]";. + /// + internal static string pip_report_multi_pkg { + get { + return ResourceManager.GetString("pip_report_multi_pkg", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to { + /// "version": "1", + /// "pip_version": "24.0", + /// "install": [ + /// { + /// "download_info": { + /// "url": "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl", + /// "archive_info": { + /// "hash": "sha256=70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6", + /// "hashes": { + /// "sha256": "70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6" + /// } + /// } [rest of string was truncated]";. + /// + internal static string pip_report_simple_extras { + get { + return ResourceManager.GetString("pip_report_simple_extras", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to { + /// "version": "1", + /// "pip_version": "24.0", + /// "install": [ + /// { + /// "download_info": { + /// "url": "https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl", + /// "archive_info": { + /// "hash": "sha256=8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254", + /// "hashes": { + /// "sha256": "8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" + /// } + /// } /// [rest of string was truncated]";. + /// + internal static string pip_report_single_pkg { + get { + return ResourceManager.GetString("pip_report_single_pkg", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to { + /// "version": "2", + /// "pip_version": "24.0", + /// "install": [ + /// { + /// "download_info": { + /// "url": "https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl", + /// "archive_info": { + /// "hash": "sha256=8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254", + /// "hashes": { + /// "sha256": "8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" + /// } + /// } /// [rest of string was truncated]";. + /// + internal static string pip_report_single_pkg_bad_version { + get { + return ResourceManager.GetString("pip_report_single_pkg_bad_version", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to { + /// "version": "1", + /// "pip_version": "24.0", + /// "install": [ + /// { + /// "download_info": { + /// "url": "https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl", + /// "archive_info": { + /// "hash": "sha256=8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254", + /// "hashes": { + /// "sha256": "8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" + /// } + /// } /// [rest of string was truncated]";. + /// + internal static string pip_report_single_pkg_invalid_pkg_version { + get { + return ResourceManager.GetString("pip_report_single_pkg_invalid_pkg_version", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to { + /// "version": 3, + /// "targets": { + /// ".NETCoreApp,Version=v2.2": { + /// "CommandLineParser/2.8.0": { + /// "type": "package", + /// "compile": { + /// "lib/netstandard2.0/_._": {} + /// }, + /// "runtime": { + /// "lib/netstandard2.0/CommandLine.dll": {} + /// } + /// }, + /// "coverlet.msbuild/2.5.1": { + /// "type": "package", + /// "build": { + /// "build/netstandard2.0/coverlet.msbuild.props": {}, + /// "build/netstandard2.0/coverlet.msbuild.targets": {} + /// } + /// }, + /// "DotNet.Glob/2.1.1": { + /// "type": "package [rest of string was truncated]";. + /// + internal static string project_assets_2_2 { + get { + return ResourceManager.GetString("project_assets_2_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to { + /// "version": 3, + /// "targets": { + /// ".NETCoreApp,Version=v2.2": { + /// "coverlet.msbuild/2.5.1": { + /// "type": "package", + /// "build": { + /// "build/netstandard2.0/coverlet.msbuild.props": {}, + /// "build/netstandard2.0/coverlet.msbuild.targets": {} + /// } + /// }, + /// "DotNet.Glob/2.1.1": { + /// "type": "package", + /// "dependencies": { + /// "NETStandard.Library": "1.6.1" + /// }, + /// "compile": { + /// "lib/netstandard1.1/DotNet.Glob.dll": {} + /// }, + /// "runtime": { + /// "lib/netstandard1.1/DotNet.Glob.dll": {} /// [rest of string was truncated]";. + /// + internal static string project_assets_2_2_additional { + get { + return ResourceManager.GetString("project_assets_2_2_additional", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to { + /// "version": 3, + /// "targets": { + /// ".NETCoreApp,Version=v3.1": { + /// "Microsoft.Extensions.DependencyModel/3.0.0": { + /// "type": "package", + /// "dependencies": { + /// "System.Text.Json": "4.6.0" + /// }, + /// "compile": { + /// "lib/netstandard2.0/Microsoft.Extensions.DependencyModel.dll": {} + /// }, + /// "runtime": { + /// "lib/netstandard2.0/Microsoft.Extensions.DependencyModel.dll": {} + /// } + /// }, + /// "Microsoft. [rest of string was truncated]";. + /// + internal static string project_assets_3_1 { + get { + return ResourceManager.GetString("project_assets_3_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to { + /// "version": 3, + /// "targets": { + /// "net42.15": { + /// "Microsoft.Extensions.Caching.Abstractions/9.0.0": { + /// "type": "package", + /// "dependencies": { + /// "Microsoft.Extensions.Primitives": "9.0.0" + /// }, + /// "compile": { + /// "lib/net9.0/Microsoft.Extensions.Caching.Abstractions.dll": { + /// "related": ".xml" + /// } + /// }, + /// "runtime": { + /// "lib/net9.0/Microsoft.Extensions.Caching.Abstractions.dll": { + /// "related": ".xml" /// [rest of string was truncated]";. + /// + internal static string project_assets_42_15_web { + get { + return ResourceManager.GetString("project_assets_42_15_web", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to { + /// "version": 3, + /// "targets": { + /// "net6.0": { + /// "Microsoft.Extensions.Primitives/6.0.0": { + /// "type": "package", + /// "dependencies": { + /// "System.Runtime.CompilerServices.Unsafe": "6.0.0" + /// }, + /// "compile": { + /// "lib/net6.0/Microsoft.Extensions.Primitives.dll": { + /// "related": ".xml" + /// } + /// }, + /// "runtime": { + /// "lib/net6.0/Microsoft.Extensions.Primitives.dll": { + /// "related": ".xml" + /// } + /// }, /// [rest of string was truncated]";. + /// + internal static string project_assets_6_0_8_0_multi_framework { + get { + return ResourceManager.GetString("project_assets_6_0_8_0_multi_framework", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to { + /// "version": 3, + /// "targets": { + /// "net8.0": { + /// "Microsoft.Extensions.Primitives/6.0.0": { + /// "type": "package", + /// "dependencies": { + /// "System.Runtime.CompilerServices.Unsafe": "6.0.0" + /// }, + /// "compile": { + /// "lib/net6.0/Microsoft.Extensions.Primitives.dll": { + /// "related": ".xml" + /// } + /// }, + /// "runtime": { + /// "lib/net6.0/Microsoft.Extensions.Primitives.dll": { + /// "related": ".xml" + /// } + /// }, /// [rest of string was truncated]";. + /// + internal static string project_assets_8_0_multi_framework { + get { + return ResourceManager.GetString("project_assets_8_0_multi_framework", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to { + /// "version": 3, + /// "targets": { + /// "net8.0": { + /// "Microsoft.Extensions.Caching.Abstractions/8.0.0": { + /// "type": "package", + /// "dependencies": { + /// "Microsoft.Extensions.Primitives": "8.0.0" + /// }, + /// "compile": { + /// "lib/net8.0/Microsoft.Extensions.Caching.Abstractions.dll": { + /// "related": ".xml" + /// } + /// }, + /// "runtime": { + /// "lib/net8.0/Microsoft.Extensions.Caching.Abstractions.dll": { + /// "related": ".xml" + /// [rest of string was truncated]";. + /// + internal static string project_assets_8_0_web { + get { + return ResourceManager.GetString("project_assets_8_0_web", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to { + /// "version": 3, + /// "targets": { + /// ".NETFramework,Version=v4.7.2": {}, + /// "net8.0": {} + /// }, + /// "libraries": {}, + /// "projectFileDependencyGroups": { + /// ".NETFramework,Version=v4.7.2": [], + /// "net8.0": [] + /// }, + /// "packageFolders": { + /// "C:\\Users\\username\\.nuget\\packages\\": {}, + /// "C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages": {} + /// }, + /// "project": { + /// "version": "1.0.0", + /// "restore": { + /// "projectUniqueName": "C:\\src\\packageDownloadSample\\package [rest of string was truncated]";. + /// + internal static string project_assets_packageDownload { + get { + return ResourceManager.GetString("project_assets_packageDownload", resourceCulture); + } + } + } +} diff --git a/test/Microsoft.ComponentDetection.Detectors.Tests/Mocks/TestResources.resx b/test/Microsoft.ComponentDetection.Detectors.Tests/Mocks/TestResources.resx index 2fda73e51..e1f936b4b 100644 --- a/test/Microsoft.ComponentDetection.Detectors.Tests/Mocks/TestResources.resx +++ b/test/Microsoft.ComponentDetection.Detectors.Tests/Mocks/TestResources.resx @@ -143,13 +143,25 @@ pip_report_single_pkg_invalid_pkg_version.json;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - ..\Resources\project_assets_2_2.json;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252 + ..\Resources\project_assets_2_2.json;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - ..\Resources\project_assets_2_2_additional.json;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252 + ..\Resources\project_assets_2_2_additional.json;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - ..\Resources\project_assets_3_1.json;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252 + ..\Resources\project_assets_3_1.json;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + ..\Resources\project_assets_42_15_web.json;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + ..\Resources\project_assets_6_0_8_0_multi_framework.json;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + ..\Resources\project_assets_8_0_multi_framework.json;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + ..\Resources\project_assets_8_0_web.json;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 ..\Resources\project_assets_packageDownload.json;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252 diff --git a/test/Microsoft.ComponentDetection.Detectors.Tests/Resources/project_assets_42_15_web.json b/test/Microsoft.ComponentDetection.Detectors.Tests/Resources/project_assets_42_15_web.json new file mode 100644 index 000000000..14358b21e --- /dev/null +++ b/test/Microsoft.ComponentDetection.Detectors.Tests/Resources/project_assets_42_15_web.json @@ -0,0 +1,437 @@ +{ + "version": 3, + "targets": { + "net42.15": { + "Microsoft.Extensions.Caching.Abstractions/9.0.0": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.Primitives": "9.0.0" + }, + "compile": { + "lib/net9.0/Microsoft.Extensions.Caching.Abstractions.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net9.0/Microsoft.Extensions.Caching.Abstractions.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/net8.0/_._": {} + } + }, + "Microsoft.Extensions.Caching.Memory/9.0.0": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "9.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.0", + "Microsoft.Extensions.Logging.Abstractions": "9.0.0", + "Microsoft.Extensions.Options": "9.0.0", + "Microsoft.Extensions.Primitives": "9.0.0" + }, + "compile": { + "lib/net9.0/Microsoft.Extensions.Caching.Memory.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net9.0/Microsoft.Extensions.Caching.Memory.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/net8.0/_._": {} + } + }, + "Microsoft.Extensions.DependencyInjection.Abstractions/9.0.0": { + "type": "package", + "compile": { + "lib/net9.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net9.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/net8.0/_._": {} + } + }, + "Microsoft.Extensions.Logging.Abstractions/9.0.0": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.0" + }, + "compile": { + "lib/net9.0/Microsoft.Extensions.Logging.Abstractions.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net9.0/Microsoft.Extensions.Logging.Abstractions.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/net8.0/Microsoft.Extensions.Logging.Abstractions.targets": {} + } + }, + "Microsoft.Extensions.Options/9.0.0": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.0", + "Microsoft.Extensions.Primitives": "9.0.0" + }, + "compile": { + "lib/net9.0/Microsoft.Extensions.Options.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net9.0/Microsoft.Extensions.Options.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/net8.0/Microsoft.Extensions.Options.targets": {} + } + }, + "Microsoft.Extensions.Primitives/9.0.0": { + "type": "package", + "compile": { + "lib/net9.0/Microsoft.Extensions.Primitives.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net9.0/Microsoft.Extensions.Primitives.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/net8.0/_._": {} + } + } + } + }, + "libraries": { + "Microsoft.Extensions.Caching.Abstractions/9.0.0": { + "sha512": "FPWZAa9c0H4dvOj351iR1jkUIs4u9ykL4Bm592yhjDyO5lCoWd+TMAHx2EMbarzUvCvgjWjJIoC6//Q9kH6YhA==", + "type": "package", + "path": "microsoft.extensions.caching.abstractions/9.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/net461/Microsoft.Extensions.Caching.Abstractions.targets", + "buildTransitive/net462/_._", + "buildTransitive/net8.0/_._", + "buildTransitive/netcoreapp2.0/Microsoft.Extensions.Caching.Abstractions.targets", + "lib/net462/Microsoft.Extensions.Caching.Abstractions.dll", + "lib/net462/Microsoft.Extensions.Caching.Abstractions.xml", + "lib/net8.0/Microsoft.Extensions.Caching.Abstractions.dll", + "lib/net8.0/Microsoft.Extensions.Caching.Abstractions.xml", + "lib/net9.0/Microsoft.Extensions.Caching.Abstractions.dll", + "lib/net9.0/Microsoft.Extensions.Caching.Abstractions.xml", + "lib/netstandard2.0/Microsoft.Extensions.Caching.Abstractions.dll", + "lib/netstandard2.0/Microsoft.Extensions.Caching.Abstractions.xml", + "microsoft.extensions.caching.abstractions.9.0.0.nupkg.sha512", + "microsoft.extensions.caching.abstractions.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "Microsoft.Extensions.Caching.Memory/9.0.0": { + "sha512": "zbnPX/JQ0pETRSUG9fNPBvpIq42Aufvs15gGYyNIMhCun9yhmWihz0WgsI7bSDPjxWTKBf8oX/zv6v2uZ3W9OQ==", + "type": "package", + "path": "microsoft.extensions.caching.memory/9.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/net461/Microsoft.Extensions.Caching.Memory.targets", + "buildTransitive/net462/_._", + "buildTransitive/net8.0/_._", + "buildTransitive/netcoreapp2.0/Microsoft.Extensions.Caching.Memory.targets", + "lib/net462/Microsoft.Extensions.Caching.Memory.dll", + "lib/net462/Microsoft.Extensions.Caching.Memory.xml", + "lib/net8.0/Microsoft.Extensions.Caching.Memory.dll", + "lib/net8.0/Microsoft.Extensions.Caching.Memory.xml", + "lib/net9.0/Microsoft.Extensions.Caching.Memory.dll", + "lib/net9.0/Microsoft.Extensions.Caching.Memory.xml", + "lib/netstandard2.0/Microsoft.Extensions.Caching.Memory.dll", + "lib/netstandard2.0/Microsoft.Extensions.Caching.Memory.xml", + "microsoft.extensions.caching.memory.9.0.0.nupkg.sha512", + "microsoft.extensions.caching.memory.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "Microsoft.Extensions.DependencyInjection.Abstractions/9.0.0": { + "sha512": "+6f2qv2a3dLwd5w6JanPIPs47CxRbnk+ZocMJUhv9NxP88VlOcJYZs9jY+MYSjxvady08bUZn6qgiNh7DadGgg==", + "type": "package", + "path": "microsoft.extensions.dependencyinjection.abstractions/9.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/net461/Microsoft.Extensions.DependencyInjection.Abstractions.targets", + "buildTransitive/net462/_._", + "buildTransitive/net8.0/_._", + "buildTransitive/netcoreapp2.0/Microsoft.Extensions.DependencyInjection.Abstractions.targets", + "lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll", + "lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.xml", + "lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll", + "lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.xml", + "lib/net9.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll", + "lib/net9.0/Microsoft.Extensions.DependencyInjection.Abstractions.xml", + "lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll", + "lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.xml", + "lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll", + "lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.xml", + "microsoft.extensions.dependencyinjection.abstractions.9.0.0.nupkg.sha512", + "microsoft.extensions.dependencyinjection.abstractions.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "Microsoft.Extensions.Logging.Abstractions/9.0.0": { + "sha512": "g0UfujELzlLbHoVG8kPKVBaW470Ewi+jnptGS9KUi6jcb+k2StujtK3m26DFSGGwQ/+bVgZfsWqNzlP6YOejvw==", + "type": "package", + "path": "microsoft.extensions.logging.abstractions/9.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "analyzers/dotnet/roslyn3.11/cs/Microsoft.Extensions.Logging.Generators.dll", + "analyzers/dotnet/roslyn3.11/cs/cs/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/de/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/es/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/fr/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/it/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/ja/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/ko/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/pl/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/pt-BR/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/ru/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/tr/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/zh-Hans/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/zh-Hant/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/Microsoft.Extensions.Logging.Generators.dll", + "analyzers/dotnet/roslyn4.0/cs/cs/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/de/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/es/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/fr/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/it/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/ja/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/ko/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/pl/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/pt-BR/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/ru/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/tr/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/zh-Hans/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/zh-Hant/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/Microsoft.Extensions.Logging.Generators.dll", + "analyzers/dotnet/roslyn4.4/cs/cs/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/de/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/es/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/fr/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/it/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/ja/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/ko/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/pl/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/pt-BR/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/ru/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/tr/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/zh-Hans/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/zh-Hant/Microsoft.Extensions.Logging.Generators.resources.dll", + "buildTransitive/net461/Microsoft.Extensions.Logging.Abstractions.targets", + "buildTransitive/net462/Microsoft.Extensions.Logging.Abstractions.targets", + "buildTransitive/net8.0/Microsoft.Extensions.Logging.Abstractions.targets", + "buildTransitive/netcoreapp2.0/Microsoft.Extensions.Logging.Abstractions.targets", + "buildTransitive/netstandard2.0/Microsoft.Extensions.Logging.Abstractions.targets", + "lib/net462/Microsoft.Extensions.Logging.Abstractions.dll", + "lib/net462/Microsoft.Extensions.Logging.Abstractions.xml", + "lib/net8.0/Microsoft.Extensions.Logging.Abstractions.dll", + "lib/net8.0/Microsoft.Extensions.Logging.Abstractions.xml", + "lib/net9.0/Microsoft.Extensions.Logging.Abstractions.dll", + "lib/net9.0/Microsoft.Extensions.Logging.Abstractions.xml", + "lib/netstandard2.0/Microsoft.Extensions.Logging.Abstractions.dll", + "lib/netstandard2.0/Microsoft.Extensions.Logging.Abstractions.xml", + "microsoft.extensions.logging.abstractions.9.0.0.nupkg.sha512", + "microsoft.extensions.logging.abstractions.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "Microsoft.Extensions.Options/9.0.0": { + "sha512": "y2146b3jrPI3Q0lokKXdKLpmXqakYbDIPDV6r3M8SqvSf45WwOTzkyfDpxnZXJsJQEpAsAqjUq5Pu8RCJMjubg==", + "type": "package", + "path": "microsoft.extensions.options/9.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "analyzers/dotnet/roslyn4.4/cs/Microsoft.Extensions.Options.SourceGeneration.dll", + "analyzers/dotnet/roslyn4.4/cs/cs/Microsoft.Extensions.Options.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/de/Microsoft.Extensions.Options.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/es/Microsoft.Extensions.Options.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/fr/Microsoft.Extensions.Options.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/it/Microsoft.Extensions.Options.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/ja/Microsoft.Extensions.Options.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/ko/Microsoft.Extensions.Options.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/pl/Microsoft.Extensions.Options.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/pt-BR/Microsoft.Extensions.Options.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/ru/Microsoft.Extensions.Options.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/tr/Microsoft.Extensions.Options.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/zh-Hans/Microsoft.Extensions.Options.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/zh-Hant/Microsoft.Extensions.Options.SourceGeneration.resources.dll", + "buildTransitive/net461/Microsoft.Extensions.Options.targets", + "buildTransitive/net462/Microsoft.Extensions.Options.targets", + "buildTransitive/net8.0/Microsoft.Extensions.Options.targets", + "buildTransitive/netcoreapp2.0/Microsoft.Extensions.Options.targets", + "buildTransitive/netstandard2.0/Microsoft.Extensions.Options.targets", + "lib/net462/Microsoft.Extensions.Options.dll", + "lib/net462/Microsoft.Extensions.Options.xml", + "lib/net8.0/Microsoft.Extensions.Options.dll", + "lib/net8.0/Microsoft.Extensions.Options.xml", + "lib/net9.0/Microsoft.Extensions.Options.dll", + "lib/net9.0/Microsoft.Extensions.Options.xml", + "lib/netstandard2.0/Microsoft.Extensions.Options.dll", + "lib/netstandard2.0/Microsoft.Extensions.Options.xml", + "lib/netstandard2.1/Microsoft.Extensions.Options.dll", + "lib/netstandard2.1/Microsoft.Extensions.Options.xml", + "microsoft.extensions.options.9.0.0.nupkg.sha512", + "microsoft.extensions.options.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "Microsoft.Extensions.Primitives/9.0.0": { + "sha512": "N3qEBzmLMYiASUlKxxFIISP4AiwuPTHF5uCh+2CWSwwzAJiIYx0kBJsS30cp1nvhSySFAVi30jecD307jV+8Kg==", + "type": "package", + "path": "microsoft.extensions.primitives/9.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/net461/Microsoft.Extensions.Primitives.targets", + "buildTransitive/net462/_._", + "buildTransitive/net8.0/_._", + "buildTransitive/netcoreapp2.0/Microsoft.Extensions.Primitives.targets", + "lib/net462/Microsoft.Extensions.Primitives.dll", + "lib/net462/Microsoft.Extensions.Primitives.xml", + "lib/net8.0/Microsoft.Extensions.Primitives.dll", + "lib/net8.0/Microsoft.Extensions.Primitives.xml", + "lib/net9.0/Microsoft.Extensions.Primitives.dll", + "lib/net9.0/Microsoft.Extensions.Primitives.xml", + "lib/netstandard2.0/Microsoft.Extensions.Primitives.dll", + "lib/netstandard2.0/Microsoft.Extensions.Primitives.xml", + "microsoft.extensions.primitives.9.0.0.nupkg.sha512", + "microsoft.extensions.primitives.nuspec", + "useSharedDesignerContext.txt" + ] + } + }, + "projectFileDependencyGroups": { + "net42.15": [ + "Microsoft.Extensions.Caching.Memory >= 9.0.0" + ] + }, + "packageFolders": { + "C:\\Users\\ericstj\\.nuget\\packages\\": {}, + "C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages": {} + }, + "project": { + "version": "1.0.0", + "restore": { + "projectUniqueName": "C:\\scratch\\web\\web.csproj", + "projectName": "web", + "projectPath": "C:\\scratch\\web\\web.csproj", + "packagesPath": "C:\\Users\\ericstj\\.nuget\\packages\\", + "outputPath": "C:\\scratch\\web\\obj\\", + "projectStyle": "PackageReference", + "fallbackFolders": [ + "C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages" + ], + "configFilePaths": [ + "C:\\scratch\\web\\NuGet.Config", + "C:\\Users\\ericstj\\AppData\\Roaming\\NuGet\\NuGet.Config", + "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config", + "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config" + ], + "originalTargetFrameworks": [ + "net42.15" + ], + "sources": { + "C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {}, + "https://api.nuget.org/v3/index.json": {}, + "https://pkgs.dev.azure.com/dnceng/internal/_packaging/9.0.100-rtm.24529.9-shipping/nuget/v3/index.json": {} + }, + "frameworks": { + "net42.15": { + "targetAlias": "net42.15", + "projectReferences": {} + } + }, + "warningProperties": { + "warnAsError": [ + "NU1605" + ] + }, + "restoreAuditProperties": { + "enableAudit": "true", + "auditLevel": "low", + "auditMode": "all" + }, + "SdkAnalysisLevel": "9.0.100" + }, + "frameworks": { + "net42.15": { + "targetAlias": "net42.15", + "dependencies": { + "Microsoft.Extensions.Caching.Memory": { + "target": "Package", + "version": "[9.0.0, )" + } + }, + "imports": [ + "net461", + "net462", + "net47", + "net471", + "net472", + "net48", + "net481" + ], + "assetTargetFallback": true, + "warn": true, + "frameworkReferences": { + "Microsoft.AspNetCore.App": { + "privateAssets": "none" + }, + "Microsoft.NETCore.App": { + "privateAssets": "all" + } + }, + "runtimeIdentifierGraphPath": "C:\\src\\dotnet\\runtime\\.dotnet\\sdk\\9.0.100-rc.1.24452.12/PortableRuntimeIdentifierGraph.json" + } + } + } +} \ No newline at end of file diff --git a/test/Microsoft.ComponentDetection.Detectors.Tests/Resources/project_assets_6_0_8_0_multi_framework.json b/test/Microsoft.ComponentDetection.Detectors.Tests/Resources/project_assets_6_0_8_0_multi_framework.json new file mode 100644 index 000000000..a311b53b7 --- /dev/null +++ b/test/Microsoft.ComponentDetection.Detectors.Tests/Resources/project_assets_6_0_8_0_multi_framework.json @@ -0,0 +1,321 @@ +{ + "version": 3, + "targets": { + "net6.0": { + "Microsoft.Extensions.Primitives/6.0.0": { + "type": "package", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + }, + "compile": { + "lib/net6.0/Microsoft.Extensions.Primitives.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net6.0/Microsoft.Extensions.Primitives.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/netcoreapp3.1/_._": {} + } + }, + "System.IO.Packaging/6.0.1": { + "type": "package", + "compile": { + "lib/net6.0/System.IO.Packaging.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net6.0/System.IO.Packaging.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/netcoreapp3.1/_._": {} + } + }, + "System.Runtime.CompilerServices.Unsafe/6.0.0": { + "type": "package", + "compile": { + "lib/net6.0/System.Runtime.CompilerServices.Unsafe.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net6.0/System.Runtime.CompilerServices.Unsafe.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/netcoreapp3.1/_._": {} + } + } + }, + "net8.0": { + "Microsoft.Extensions.Primitives/6.0.0": { + "type": "package", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + }, + "compile": { + "lib/net6.0/Microsoft.Extensions.Primitives.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net6.0/Microsoft.Extensions.Primitives.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/netcoreapp3.1/_._": {} + } + }, + "System.IO.Packaging/6.0.1": { + "type": "package", + "compile": { + "lib/net6.0/System.IO.Packaging.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net6.0/System.IO.Packaging.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/netcoreapp3.1/_._": {} + } + }, + "System.Runtime.CompilerServices.Unsafe/6.0.0": { + "type": "package", + "compile": { + "lib/net6.0/System.Runtime.CompilerServices.Unsafe.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net6.0/System.Runtime.CompilerServices.Unsafe.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/netcoreapp3.1/_._": {} + } + } + } + }, + "libraries": { + "Microsoft.Extensions.Primitives/6.0.0": { + "sha512": "9+PnzmQFfEFNR9J2aDTfJGGupShHjOuGw4VUv+JB044biSHrnmCIMD+mJHmb2H7YryrfBEXDurxQ47gJZdCKNQ==", + "type": "package", + "path": "microsoft.extensions.primitives/6.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/netcoreapp2.0/Microsoft.Extensions.Primitives.targets", + "buildTransitive/netcoreapp3.1/_._", + "lib/net461/Microsoft.Extensions.Primitives.dll", + "lib/net461/Microsoft.Extensions.Primitives.xml", + "lib/net6.0/Microsoft.Extensions.Primitives.dll", + "lib/net6.0/Microsoft.Extensions.Primitives.xml", + "lib/netcoreapp3.1/Microsoft.Extensions.Primitives.dll", + "lib/netcoreapp3.1/Microsoft.Extensions.Primitives.xml", + "lib/netstandard2.0/Microsoft.Extensions.Primitives.dll", + "lib/netstandard2.0/Microsoft.Extensions.Primitives.xml", + "microsoft.extensions.primitives.6.0.0.nupkg.sha512", + "microsoft.extensions.primitives.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "System.IO.Packaging/6.0.1": { + "sha512": "uU8v5JFutuypHiG+4E1jJH+pudE2UBJcKMO4O3bwZBTQn0+K3I2YOh21M6TfQy+Jr8fT2zxTxb9bGqnRxnfo4A==", + "type": "package", + "path": "system.io.packaging/6.0.1", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/netcoreapp2.0/System.IO.Packaging.targets", + "buildTransitive/netcoreapp3.1/_._", + "lib/net461/System.IO.Packaging.dll", + "lib/net461/System.IO.Packaging.xml", + "lib/net6.0/System.IO.Packaging.dll", + "lib/net6.0/System.IO.Packaging.xml", + "lib/netstandard2.0/System.IO.Packaging.dll", + "lib/netstandard2.0/System.IO.Packaging.xml", + "system.io.packaging.6.0.1.nupkg.sha512", + "system.io.packaging.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "System.Runtime.CompilerServices.Unsafe/6.0.0": { + "sha512": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==", + "type": "package", + "path": "system.runtime.compilerservices.unsafe/6.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/netcoreapp2.0/System.Runtime.CompilerServices.Unsafe.targets", + "buildTransitive/netcoreapp3.1/_._", + "lib/net461/System.Runtime.CompilerServices.Unsafe.dll", + "lib/net461/System.Runtime.CompilerServices.Unsafe.xml", + "lib/net6.0/System.Runtime.CompilerServices.Unsafe.dll", + "lib/net6.0/System.Runtime.CompilerServices.Unsafe.xml", + "lib/netcoreapp3.1/System.Runtime.CompilerServices.Unsafe.dll", + "lib/netcoreapp3.1/System.Runtime.CompilerServices.Unsafe.xml", + "lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.dll", + "lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.xml", + "system.runtime.compilerservices.unsafe.6.0.0.nupkg.sha512", + "system.runtime.compilerservices.unsafe.nuspec", + "useSharedDesignerContext.txt" + ] + } + }, + "projectFileDependencyGroups": { + "net6.0": [ + "Microsoft.Extensions.Primitives >= 6.0.0", + "System.IO.Packaging >= 6.0.1" + ], + "net8.0": [ + "Microsoft.Extensions.Primitives >= 6.0.0", + "System.IO.Packaging >= 6.0.1" + ] + }, + "packageFolders": { + "C:\\Users\\ericstj\\.nuget\\packages\\": {}, + "C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages": {} + }, + "project": { + "version": "1.0.0", + "restore": { + "projectUniqueName": "C:\\scratch\\classlibFramework\\classlibFramework.csproj", + "projectName": "classlibFramework", + "projectPath": "C:\\scratch\\classlibFramework\\classlibFramework.csproj", + "packagesPath": "C:\\Users\\ericstj\\.nuget\\packages\\", + "outputPath": "C:\\scratch\\classlibFramework\\obj\\", + "projectStyle": "PackageReference", + "crossTargeting": true, + "fallbackFolders": [ + "C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages" + ], + "configFilePaths": [ + "C:\\Users\\ericstj\\AppData\\Roaming\\NuGet\\NuGet.Config", + "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config", + "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config" + ], + "originalTargetFrameworks": [ + "net6.0", + "net8.0" + ], + "sources": { + "C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {}, + "C:\\Program Files\\dotnet\\library-packs": {}, + "https://api.nuget.org/v3/index.json": {} + }, + "frameworks": { + "net6.0": { + "targetAlias": "net6.0", + "projectReferences": {} + }, + "net8.0": { + "targetAlias": "net8.0", + "projectReferences": {} + } + }, + "warningProperties": { + "warnAsError": [ + "NU1605" + ] + }, + "restoreAuditProperties": { + "enableAudit": "true", + "auditLevel": "low", + "auditMode": "all" + }, + "SdkAnalysisLevel": "9.0.100" + }, + "frameworks": { + "net6.0": { + "targetAlias": "net6.0", + "dependencies": { + "Microsoft.Extensions.Primitives": { + "target": "Package", + "version": "[6.0.0, )" + }, + "System.IO.Packaging": { + "target": "Package", + "version": "[6.0.1, )" + } + }, + "imports": [ + "net461", + "net462", + "net47", + "net471", + "net472", + "net48", + "net481" + ], + "assetTargetFallback": true, + "warn": true, + "frameworkReferences": { + "Microsoft.AspNetCore.App": { + "privateAssets": "none" + }, + "Microsoft.NETCore.App": { + "privateAssets": "all" + } + }, + "runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\9.0.100-rc.2.24474.11\\RuntimeIdentifierGraph.json" + }, + "net8.0": { + "targetAlias": "net8.0", + "dependencies": { + "Microsoft.Extensions.Primitives": { + "target": "Package", + "version": "[6.0.0, )" + }, + "System.IO.Packaging": { + "target": "Package", + "version": "[6.0.1, )" + } + }, + "imports": [ + "net461", + "net462", + "net47", + "net471", + "net472", + "net48", + "net481" + ], + "assetTargetFallback": true, + "warn": true, + "frameworkReferences": { + "Microsoft.AspNetCore.App": { + "privateAssets": "none" + }, + "Microsoft.NETCore.App": { + "privateAssets": "all" + }, + "Microsoft.WindowsDesktop.App": { + "privateAssets": "none" + } + }, + "runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\9.0.100-rc.2.24474.11/PortableRuntimeIdentifierGraph.json" + } + } + } +} \ No newline at end of file diff --git a/test/Microsoft.ComponentDetection.Detectors.Tests/Resources/project_assets_8_0_multi_framework.json b/test/Microsoft.ComponentDetection.Detectors.Tests/Resources/project_assets_8_0_multi_framework.json new file mode 100644 index 000000000..09468925e --- /dev/null +++ b/test/Microsoft.ComponentDetection.Detectors.Tests/Resources/project_assets_8_0_multi_framework.json @@ -0,0 +1,226 @@ +{ + "version": 3, + "targets": { + "net8.0": { + "Microsoft.Extensions.Primitives/6.0.0": { + "type": "package", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + }, + "compile": { + "lib/net6.0/Microsoft.Extensions.Primitives.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net6.0/Microsoft.Extensions.Primitives.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/netcoreapp3.1/_._": {} + } + }, + "System.IO.Packaging/6.0.1": { + "type": "package", + "compile": { + "lib/net6.0/System.IO.Packaging.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net6.0/System.IO.Packaging.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/netcoreapp3.1/_._": {} + } + }, + "System.Runtime.CompilerServices.Unsafe/6.0.0": { + "type": "package", + "compile": { + "lib/net6.0/System.Runtime.CompilerServices.Unsafe.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net6.0/System.Runtime.CompilerServices.Unsafe.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/netcoreapp3.1/_._": {} + } + } + } + }, + "libraries": { + "Microsoft.Extensions.Primitives/6.0.0": { + "sha512": "9+PnzmQFfEFNR9J2aDTfJGGupShHjOuGw4VUv+JB044biSHrnmCIMD+mJHmb2H7YryrfBEXDurxQ47gJZdCKNQ==", + "type": "package", + "path": "microsoft.extensions.primitives/6.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/netcoreapp2.0/Microsoft.Extensions.Primitives.targets", + "buildTransitive/netcoreapp3.1/_._", + "lib/net461/Microsoft.Extensions.Primitives.dll", + "lib/net461/Microsoft.Extensions.Primitives.xml", + "lib/net6.0/Microsoft.Extensions.Primitives.dll", + "lib/net6.0/Microsoft.Extensions.Primitives.xml", + "lib/netcoreapp3.1/Microsoft.Extensions.Primitives.dll", + "lib/netcoreapp3.1/Microsoft.Extensions.Primitives.xml", + "lib/netstandard2.0/Microsoft.Extensions.Primitives.dll", + "lib/netstandard2.0/Microsoft.Extensions.Primitives.xml", + "microsoft.extensions.primitives.6.0.0.nupkg.sha512", + "microsoft.extensions.primitives.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "System.IO.Packaging/6.0.1": { + "sha512": "uU8v5JFutuypHiG+4E1jJH+pudE2UBJcKMO4O3bwZBTQn0+K3I2YOh21M6TfQy+Jr8fT2zxTxb9bGqnRxnfo4A==", + "type": "package", + "path": "system.io.packaging/6.0.1", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/netcoreapp2.0/System.IO.Packaging.targets", + "buildTransitive/netcoreapp3.1/_._", + "lib/net461/System.IO.Packaging.dll", + "lib/net461/System.IO.Packaging.xml", + "lib/net6.0/System.IO.Packaging.dll", + "lib/net6.0/System.IO.Packaging.xml", + "lib/netstandard2.0/System.IO.Packaging.dll", + "lib/netstandard2.0/System.IO.Packaging.xml", + "system.io.packaging.6.0.1.nupkg.sha512", + "system.io.packaging.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "System.Runtime.CompilerServices.Unsafe/6.0.0": { + "sha512": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==", + "type": "package", + "path": "system.runtime.compilerservices.unsafe/6.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/netcoreapp2.0/System.Runtime.CompilerServices.Unsafe.targets", + "buildTransitive/netcoreapp3.1/_._", + "lib/net461/System.Runtime.CompilerServices.Unsafe.dll", + "lib/net461/System.Runtime.CompilerServices.Unsafe.xml", + "lib/net6.0/System.Runtime.CompilerServices.Unsafe.dll", + "lib/net6.0/System.Runtime.CompilerServices.Unsafe.xml", + "lib/netcoreapp3.1/System.Runtime.CompilerServices.Unsafe.dll", + "lib/netcoreapp3.1/System.Runtime.CompilerServices.Unsafe.xml", + "lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.dll", + "lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.xml", + "system.runtime.compilerservices.unsafe.6.0.0.nupkg.sha512", + "system.runtime.compilerservices.unsafe.nuspec", + "useSharedDesignerContext.txt" + ] + } + }, + "projectFileDependencyGroups": { + "net8.0": [ + "Microsoft.Extensions.Primitives >= 6.0.0", + "System.IO.Packaging >= 6.0.1" + ] + }, + "packageFolders": { + "C:\\Users\\ericstj\\.nuget\\packages\\": {}, + "C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages": {} + }, + "project": { + "version": "1.0.0", + "restore": { + "projectUniqueName": "C:\\scratch\\classlibFramework\\classlibFramework.csproj", + "projectName": "classlibFramework", + "projectPath": "C:\\scratch\\classlibFramework\\classlibFramework.csproj", + "packagesPath": "C:\\Users\\ericstj\\.nuget\\packages\\", + "outputPath": "C:\\scratch\\classlibFramework\\obj\\", + "projectStyle": "PackageReference", + "crossTargeting": true, + "fallbackFolders": [ + "C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages" + ], + "configFilePaths": [ + "C:\\Users\\ericstj\\AppData\\Roaming\\NuGet\\NuGet.Config", + "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config", + "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config" + ], + "originalTargetFrameworks": [ + "net8.0" + ], + "sources": { + "C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {}, + "C:\\Program Files\\dotnet\\library-packs": {}, + "https://api.nuget.org/v3/index.json": {} + }, + "frameworks": { + "net8.0": { + "targetAlias": "net8.0", + "projectReferences": {} + } + }, + "warningProperties": { + "warnAsError": [ + "NU1605" + ] + }, + "restoreAuditProperties": { + "enableAudit": "true", + "auditLevel": "low", + "auditMode": "all" + }, + "SdkAnalysisLevel": "9.0.100" + }, + "frameworks": { + "net8.0": { + "targetAlias": "net8.0", + "dependencies": { + "Microsoft.Extensions.Primitives": { + "target": "Package", + "version": "[6.0.0, )" + }, + "System.IO.Packaging": { + "target": "Package", + "version": "[6.0.1, )" + } + }, + "imports": [ + "net461", + "net462", + "net47", + "net471", + "net472", + "net48", + "net481" + ], + "assetTargetFallback": true, + "warn": true, + "frameworkReferences": { + "Microsoft.AspNetCore.App": { + "privateAssets": "none" + }, + "Microsoft.NETCore.App": { + "privateAssets": "all" + }, + "Microsoft.WindowsDesktop.App": { + "privateAssets": "none" + } + }, + "runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\9.0.100-rc.2.24474.11/PortableRuntimeIdentifierGraph.json" + } + } + } +} \ No newline at end of file diff --git a/test/Microsoft.ComponentDetection.Detectors.Tests/Resources/project_assets_8_0_web.json b/test/Microsoft.ComponentDetection.Detectors.Tests/Resources/project_assets_8_0_web.json new file mode 100644 index 000000000..ebbfffb12 --- /dev/null +++ b/test/Microsoft.ComponentDetection.Detectors.Tests/Resources/project_assets_8_0_web.json @@ -0,0 +1,460 @@ +{ + "version": 3, + "targets": { + "net8.0": { + "Microsoft.Extensions.Caching.Abstractions/8.0.0": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.Primitives": "8.0.0" + }, + "compile": { + "lib/net8.0/Microsoft.Extensions.Caching.Abstractions.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net8.0/Microsoft.Extensions.Caching.Abstractions.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/net6.0/_._": {} + } + }, + "Microsoft.Extensions.Caching.Memory/8.0.0": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "8.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", + "Microsoft.Extensions.Logging.Abstractions": "8.0.0", + "Microsoft.Extensions.Options": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + }, + "compile": { + "lib/net8.0/Microsoft.Extensions.Caching.Memory.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net8.0/Microsoft.Extensions.Caching.Memory.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/net6.0/_._": {} + } + }, + "Microsoft.Extensions.DependencyInjection.Abstractions/8.0.0": { + "type": "package", + "compile": { + "lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/net6.0/_._": {} + } + }, + "Microsoft.Extensions.Logging.Abstractions/8.0.0": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0" + }, + "compile": { + "lib/net8.0/Microsoft.Extensions.Logging.Abstractions.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net8.0/Microsoft.Extensions.Logging.Abstractions.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/net6.0/Microsoft.Extensions.Logging.Abstractions.targets": {} + } + }, + "Microsoft.Extensions.Options/8.0.0": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + }, + "compile": { + "lib/net8.0/Microsoft.Extensions.Options.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net8.0/Microsoft.Extensions.Options.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/net6.0/Microsoft.Extensions.Options.targets": {} + } + }, + "Microsoft.Extensions.Primitives/8.0.0": { + "type": "package", + "compile": { + "lib/net8.0/Microsoft.Extensions.Primitives.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/net8.0/Microsoft.Extensions.Primitives.dll": { + "related": ".xml" + } + }, + "build": { + "buildTransitive/net6.0/_._": {} + } + } + } + }, + "libraries": { + "Microsoft.Extensions.Caching.Abstractions/8.0.0": { + "sha512": "3L/p+NiQYKkJoZYScaG/oZFt9pY/9TSpaEOBshJybd1mQXShxi6YWYkW/m1Lu//Fvc8WQRXbgy0Tj8DoHddVOA==", + "type": "package", + "path": "microsoft.extensions.caching.abstractions/8.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/net461/Microsoft.Extensions.Caching.Abstractions.targets", + "buildTransitive/net462/_._", + "buildTransitive/net6.0/_._", + "buildTransitive/netcoreapp2.0/Microsoft.Extensions.Caching.Abstractions.targets", + "lib/net462/Microsoft.Extensions.Caching.Abstractions.dll", + "lib/net462/Microsoft.Extensions.Caching.Abstractions.xml", + "lib/net6.0/Microsoft.Extensions.Caching.Abstractions.dll", + "lib/net6.0/Microsoft.Extensions.Caching.Abstractions.xml", + "lib/net7.0/Microsoft.Extensions.Caching.Abstractions.dll", + "lib/net7.0/Microsoft.Extensions.Caching.Abstractions.xml", + "lib/net8.0/Microsoft.Extensions.Caching.Abstractions.dll", + "lib/net8.0/Microsoft.Extensions.Caching.Abstractions.xml", + "lib/netstandard2.0/Microsoft.Extensions.Caching.Abstractions.dll", + "lib/netstandard2.0/Microsoft.Extensions.Caching.Abstractions.xml", + "microsoft.extensions.caching.abstractions.8.0.0.nupkg.sha512", + "microsoft.extensions.caching.abstractions.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "Microsoft.Extensions.Caching.Memory/8.0.0": { + "sha512": "xHj036WyhEeOlF9TbyHKRC0bnycHYluiKsxwBDiJs9hdDWPuq0lrEnFQ+czVSZysHrYHoSiA0lfg9kMIHZCWHA==", + "type": "package", + "path": "microsoft.extensions.caching.memory/8.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/net461/Microsoft.Extensions.Caching.Memory.targets", + "buildTransitive/net462/_._", + "buildTransitive/net6.0/_._", + "buildTransitive/netcoreapp2.0/Microsoft.Extensions.Caching.Memory.targets", + "lib/net462/Microsoft.Extensions.Caching.Memory.dll", + "lib/net462/Microsoft.Extensions.Caching.Memory.xml", + "lib/net6.0/Microsoft.Extensions.Caching.Memory.dll", + "lib/net6.0/Microsoft.Extensions.Caching.Memory.xml", + "lib/net7.0/Microsoft.Extensions.Caching.Memory.dll", + "lib/net7.0/Microsoft.Extensions.Caching.Memory.xml", + "lib/net8.0/Microsoft.Extensions.Caching.Memory.dll", + "lib/net8.0/Microsoft.Extensions.Caching.Memory.xml", + "lib/netstandard2.0/Microsoft.Extensions.Caching.Memory.dll", + "lib/netstandard2.0/Microsoft.Extensions.Caching.Memory.xml", + "microsoft.extensions.caching.memory.8.0.0.nupkg.sha512", + "microsoft.extensions.caching.memory.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "Microsoft.Extensions.DependencyInjection.Abstractions/8.0.0": { + "sha512": "sNL2FZtlPfZgmOvKfu/dORFtOZh1GwGZht5WpQ0WcwXDBcAP0Tt7JcqK8t9u6aQgOxDsEznIxBUR1HZReLkFAQ==", + "type": "package", + "path": "microsoft.extensions.dependencyinjection.abstractions/8.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/net461/Microsoft.Extensions.DependencyInjection.Abstractions.targets", + "buildTransitive/net462/_._", + "buildTransitive/net6.0/_._", + "buildTransitive/netcoreapp2.0/Microsoft.Extensions.DependencyInjection.Abstractions.targets", + "lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.dll", + "lib/net462/Microsoft.Extensions.DependencyInjection.Abstractions.xml", + "lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll", + "lib/net6.0/Microsoft.Extensions.DependencyInjection.Abstractions.xml", + "lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll", + "lib/net7.0/Microsoft.Extensions.DependencyInjection.Abstractions.xml", + "lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll", + "lib/net8.0/Microsoft.Extensions.DependencyInjection.Abstractions.xml", + "lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll", + "lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.xml", + "lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.dll", + "lib/netstandard2.1/Microsoft.Extensions.DependencyInjection.Abstractions.xml", + "microsoft.extensions.dependencyinjection.abstractions.8.0.0.nupkg.sha512", + "microsoft.extensions.dependencyinjection.abstractions.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "Microsoft.Extensions.Logging.Abstractions/8.0.0": { + "sha512": "bvAwcH+EyTqlVM1rk05cria/R9myWNnoMHoAFkQbevv0klE3l8BDvWcDsFjddQb1vMOof8gBG2yt73y4Gsmb5Q==", + "type": "package", + "path": "microsoft.extensions.logging.abstractions/8.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "analyzers/dotnet/roslyn3.11/cs/Microsoft.Extensions.Logging.Generators.dll", + "analyzers/dotnet/roslyn3.11/cs/cs/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/de/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/es/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/fr/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/it/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/ja/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/ko/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/pl/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/pt-BR/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/ru/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/tr/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/zh-Hans/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn3.11/cs/zh-Hant/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/Microsoft.Extensions.Logging.Generators.dll", + "analyzers/dotnet/roslyn4.0/cs/cs/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/de/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/es/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/fr/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/it/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/ja/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/ko/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/pl/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/pt-BR/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/ru/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/tr/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/zh-Hans/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.0/cs/zh-Hant/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/Microsoft.Extensions.Logging.Generators.dll", + "analyzers/dotnet/roslyn4.4/cs/cs/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/de/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/es/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/fr/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/it/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/ja/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/ko/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/pl/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/pt-BR/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/ru/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/tr/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/zh-Hans/Microsoft.Extensions.Logging.Generators.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/zh-Hant/Microsoft.Extensions.Logging.Generators.resources.dll", + "buildTransitive/net461/Microsoft.Extensions.Logging.Abstractions.targets", + "buildTransitive/net462/Microsoft.Extensions.Logging.Abstractions.targets", + "buildTransitive/net6.0/Microsoft.Extensions.Logging.Abstractions.targets", + "buildTransitive/netcoreapp2.0/Microsoft.Extensions.Logging.Abstractions.targets", + "buildTransitive/netstandard2.0/Microsoft.Extensions.Logging.Abstractions.targets", + "lib/net462/Microsoft.Extensions.Logging.Abstractions.dll", + "lib/net462/Microsoft.Extensions.Logging.Abstractions.xml", + "lib/net6.0/Microsoft.Extensions.Logging.Abstractions.dll", + "lib/net6.0/Microsoft.Extensions.Logging.Abstractions.xml", + "lib/net7.0/Microsoft.Extensions.Logging.Abstractions.dll", + "lib/net7.0/Microsoft.Extensions.Logging.Abstractions.xml", + "lib/net8.0/Microsoft.Extensions.Logging.Abstractions.dll", + "lib/net8.0/Microsoft.Extensions.Logging.Abstractions.xml", + "lib/netstandard2.0/Microsoft.Extensions.Logging.Abstractions.dll", + "lib/netstandard2.0/Microsoft.Extensions.Logging.Abstractions.xml", + "microsoft.extensions.logging.abstractions.8.0.0.nupkg.sha512", + "microsoft.extensions.logging.abstractions.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "Microsoft.Extensions.Options/8.0.0": { + "sha512": "Lg4fynTdkajwYVv2BqVWNEgG4OTCPKCjLcT1DQrbrYn2yaC4Lwi2yWPIF7N+QxmadgEl2qYAHZrdfPXc/rvuIQ==", + "type": "package", + "path": "microsoft.extensions.options/8.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "analyzers/dotnet/roslyn4.4/cs/Microsoft.Extensions.Options.SourceGeneration.dll", + "analyzers/dotnet/roslyn4.4/cs/cs/Microsoft.Extensions.Options.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/de/Microsoft.Extensions.Options.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/es/Microsoft.Extensions.Options.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/fr/Microsoft.Extensions.Options.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/it/Microsoft.Extensions.Options.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/ja/Microsoft.Extensions.Options.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/ko/Microsoft.Extensions.Options.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/pl/Microsoft.Extensions.Options.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/pt-BR/Microsoft.Extensions.Options.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/ru/Microsoft.Extensions.Options.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/tr/Microsoft.Extensions.Options.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/zh-Hans/Microsoft.Extensions.Options.SourceGeneration.resources.dll", + "analyzers/dotnet/roslyn4.4/cs/zh-Hant/Microsoft.Extensions.Options.SourceGeneration.resources.dll", + "buildTransitive/net461/Microsoft.Extensions.Options.targets", + "buildTransitive/net462/Microsoft.Extensions.Options.targets", + "buildTransitive/net6.0/Microsoft.Extensions.Options.targets", + "buildTransitive/netcoreapp2.0/Microsoft.Extensions.Options.targets", + "buildTransitive/netstandard2.0/Microsoft.Extensions.Options.targets", + "lib/net462/Microsoft.Extensions.Options.dll", + "lib/net462/Microsoft.Extensions.Options.xml", + "lib/net6.0/Microsoft.Extensions.Options.dll", + "lib/net6.0/Microsoft.Extensions.Options.xml", + "lib/net7.0/Microsoft.Extensions.Options.dll", + "lib/net7.0/Microsoft.Extensions.Options.xml", + "lib/net8.0/Microsoft.Extensions.Options.dll", + "lib/net8.0/Microsoft.Extensions.Options.xml", + "lib/netstandard2.0/Microsoft.Extensions.Options.dll", + "lib/netstandard2.0/Microsoft.Extensions.Options.xml", + "lib/netstandard2.1/Microsoft.Extensions.Options.dll", + "lib/netstandard2.1/Microsoft.Extensions.Options.xml", + "microsoft.extensions.options.8.0.0.nupkg.sha512", + "microsoft.extensions.options.nuspec", + "useSharedDesignerContext.txt" + ] + }, + "Microsoft.Extensions.Primitives/8.0.0": { + "sha512": "aXC8i3SM4xwTLtqpRc3W2Xx/+t9sRJR7MPxq9jm65qRwQyuFVK57c1acu6Ggl6RwR8jCB9xXHdxYb0goKbT6OQ==", + "type": "package", + "path": "microsoft.extensions.primitives/8.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "Icon.png", + "LICENSE.TXT", + "PACKAGE.md", + "THIRD-PARTY-NOTICES.TXT", + "buildTransitive/net461/Microsoft.Extensions.Primitives.targets", + "buildTransitive/net462/_._", + "buildTransitive/net6.0/_._", + "buildTransitive/netcoreapp2.0/Microsoft.Extensions.Primitives.targets", + "lib/net462/Microsoft.Extensions.Primitives.dll", + "lib/net462/Microsoft.Extensions.Primitives.xml", + "lib/net6.0/Microsoft.Extensions.Primitives.dll", + "lib/net6.0/Microsoft.Extensions.Primitives.xml", + "lib/net7.0/Microsoft.Extensions.Primitives.dll", + "lib/net7.0/Microsoft.Extensions.Primitives.xml", + "lib/net8.0/Microsoft.Extensions.Primitives.dll", + "lib/net8.0/Microsoft.Extensions.Primitives.xml", + "lib/netstandard2.0/Microsoft.Extensions.Primitives.dll", + "lib/netstandard2.0/Microsoft.Extensions.Primitives.xml", + "microsoft.extensions.primitives.8.0.0.nupkg.sha512", + "microsoft.extensions.primitives.nuspec", + "useSharedDesignerContext.txt" + ] + } + }, + "projectFileDependencyGroups": { + "net8.0": [ + "Microsoft.Extensions.Caching.Memory >= 8.0.0" + ] + }, + "packageFolders": { + "C:\\Users\\ericstj\\.nuget\\packages\\": {}, + "C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages": {} + }, + "project": { + "version": "1.0.0", + "restore": { + "projectUniqueName": "C:\\scratch\\web\\web.csproj", + "projectName": "web", + "projectPath": "C:\\scratch\\web\\web.csproj", + "packagesPath": "C:\\Users\\ericstj\\.nuget\\packages\\", + "outputPath": "C:\\scratch\\web\\obj\\", + "projectStyle": "PackageReference", + "fallbackFolders": [ + "C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages" + ], + "configFilePaths": [ + "C:\\Users\\ericstj\\AppData\\Roaming\\NuGet\\NuGet.Config", + "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config", + "C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config" + ], + "originalTargetFrameworks": [ + "net8.0" + ], + "sources": { + "C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {}, + "C:\\Program Files\\dotnet\\library-packs": {}, + "https://api.nuget.org/v3/index.json": {} + }, + "frameworks": { + "net8.0": { + "targetAlias": "net8.0", + "projectReferences": {} + } + }, + "warningProperties": { + "warnAsError": [ + "NU1605" + ] + }, + "restoreAuditProperties": { + "enableAudit": "true", + "auditLevel": "low", + "auditMode": "all" + }, + "SdkAnalysisLevel": "9.0.100" + }, + "frameworks": { + "net8.0": { + "targetAlias": "net8.0", + "dependencies": { + "Microsoft.Extensions.Caching.Memory": { + "target": "Package", + "version": "[8.0.0, )" + } + }, + "imports": [ + "net461", + "net462", + "net47", + "net471", + "net472", + "net48", + "net481" + ], + "assetTargetFallback": true, + "warn": true, + "frameworkReferences": { + "Microsoft.AspNetCore.App": { + "privateAssets": "none" + }, + "Microsoft.NETCore.App": { + "privateAssets": "all" + } + }, + "runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\9.0.100-rc.2.24474.11/PortableRuntimeIdentifierGraph.json" + } + } + }, + "logs": [ + { + "code": "NU1903", + "level": "Warning", + "warningLevel": 1, + "message": "Package 'Microsoft.Extensions.Caching.Memory' 8.0.0 has a known high severity vulnerability, https://github.com/advisories/GHSA-qj66-m88j-hmgj", + "libraryId": "Microsoft.Extensions.Caching.Memory", + "targetGraphs": [ + "net8.0" + ] + } + ] +} \ No newline at end of file diff --git a/test/Microsoft.ComponentDetection.Detectors.Tests/nuget/NuGetPackageReferenceFrameworkAwareDetectorTests.cs b/test/Microsoft.ComponentDetection.Detectors.Tests/nuget/NuGetPackageReferenceFrameworkAwareDetectorTests.cs index 922509b37..99cff08a1 100644 --- a/test/Microsoft.ComponentDetection.Detectors.Tests/nuget/NuGetPackageReferenceFrameworkAwareDetectorTests.cs +++ b/test/Microsoft.ComponentDetection.Detectors.Tests/nuget/NuGetPackageReferenceFrameworkAwareDetectorTests.cs @@ -68,7 +68,7 @@ public async Task ScanDirectoryAsync_Base_2_2_additional_VerificationAsync() detectedComponents.Should().HaveCount(68); var nonDevComponents = detectedComponents.Where(c => !componentRecorder.GetEffectiveDevDependencyValue(c.Component.Id).GetValueOrDefault()); - nonDevComponents.Should().HaveCount(23); + nonDevComponents.Should().HaveCount(22); nonDevComponents.Select(x => x.Component).Cast().FirstOrDefault(x => x.Name.Contains("Polly")).Should().NotBeNull(); nonDevComponents.Select(x => x.Component).Cast().Count(x => x.Name.Contains("System.Composition")).Should().Be(5); @@ -266,6 +266,59 @@ public async Task ScanDirectoryAsync_DependencyGraph_3_1_VerificationAsync() } } + [TestMethod] + public async Task ScanDirectoryAsync_ExcludedFrameworkComponent_8_0_web_VerificationAsync() + { + var osAgnostic = this.Convert31SampleToOSAgnostic(TestResources.project_assets_8_0_web); + var (scanResult, componentRecorder) = await this.DetectorTestUtility + .WithFile(this.projectAssetsJsonFileName, osAgnostic) + .ExecuteDetectorAsync(); + + var detectedComponents = componentRecorder.GetDetectedComponents(); + detectedComponents.Should().AllSatisfy(c => componentRecorder.GetEffectiveDevDependencyValue(c.Component.Id).GetValueOrDefault(), "All should be development dependencies"); + } + + [TestMethod] + public async Task ScanDirectoryAsync_ExcludedFrameworkComponent_42_15_web_VerificationAsync() + { + var osAgnostic = this.Convert31SampleToOSAgnostic(TestResources.project_assets_42_15_web); + var (scanResult, componentRecorder) = await this.DetectorTestUtility + .WithFile(this.projectAssetsJsonFileName, osAgnostic) + .ExecuteDetectorAsync(); + + // net42.15 is not a known framework, but it can import framework packages from the closest known framework. + var detectedComponents = componentRecorder.GetDetectedComponents(); + detectedComponents.Should().AllSatisfy(c => componentRecorder.GetEffectiveDevDependencyValue(c.Component.Id).GetValueOrDefault(), "All should be development dependencies"); + } + + [TestMethod] + public async Task ScanDirectoryAsync_ExcludedFrameworkComponent_8_0_multi_framework_VerificationAsync() + { + var osAgnostic = this.Convert31SampleToOSAgnostic(TestResources.project_assets_8_0_multi_framework); + var (scanResult, componentRecorder) = await this.DetectorTestUtility + .WithFile(this.projectAssetsJsonFileName, osAgnostic) + .ExecuteDetectorAsync(); + + var developmentDependencies = componentRecorder.GetDetectedComponents().Where(c => componentRecorder.GetEffectiveDevDependencyValue(c.Component.Id).GetValueOrDefault()); + developmentDependencies.Should().HaveCount(3, "Omitted framework assemblies are missing."); + developmentDependencies.Should().Contain(c => c.Component.Id.StartsWith("Microsoft.Extensions.Primitives "), "Microsoft.Extensions.Primitives should be treated as a development dependency."); + developmentDependencies.Should().Contain(c => c.Component.Id.StartsWith("System.IO.Packaging "), "System.IO.Packaging should be treated as a development dependency."); + } + + [TestMethod] + public async Task ScanDirectoryAsync_ExcludedFrameworkComponent_6_0_8_0_multi_framework_VerificationAsync() + { + var osAgnostic = this.Convert31SampleToOSAgnostic(TestResources.project_assets_6_0_8_0_multi_framework); + var (scanResult, componentRecorder) = await this.DetectorTestUtility + .WithFile(this.projectAssetsJsonFileName, osAgnostic) + .ExecuteDetectorAsync(); + + var developmentDependencies = componentRecorder.GetDetectedComponents().Where(c => componentRecorder.GetEffectiveDevDependencyValue(c.Component.Id).GetValueOrDefault()); + developmentDependencies.Should().HaveCount(2, "Omitted framework assemblies are missing."); + developmentDependencies.Should().Contain(c => c.Component.Id.StartsWith("Microsoft.Extensions.Primitives "), "Microsoft.Extensions.Primitives should be treated as a development dependency."); + developmentDependencies.Should().NotContain(c => c.Component.Id.StartsWith("System.IO.Packaging "), "System.IO.Packaging should not be treated as a development dependency."); + } + [TestMethod] public async Task ScanDirectoryAsync_PackageDownload_VerificationAsync() { From 7721f9924cd4d3a2ba3c4671eb9244b21f43fa67 Mon Sep 17 00:00:00 2001 From: Greg Villicana <58237075+grvillic@users.noreply.github.com> Date: Mon, 18 Nov 2024 10:25:02 -0800 Subject: [PATCH 06/10] Fix detector component filepath custom overrides (#1306) * Fix detector component filepath custom overrides --- .../DefaultGraphTranslationService.cs | 6 +- .../DefaultGraphTranslationServiceTests.cs | 69 +++++++++++++++++++ 2 files changed, 74 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.ComponentDetection.Orchestrator/Services/GraphTranslation/DefaultGraphTranslationService.cs b/src/Microsoft.ComponentDetection.Orchestrator/Services/GraphTranslation/DefaultGraphTranslationService.cs index cb00860a4..ceed83e84 100644 --- a/src/Microsoft.ComponentDetection.Orchestrator/Services/GraphTranslation/DefaultGraphTranslationService.cs +++ b/src/Microsoft.ComponentDetection.Orchestrator/Services/GraphTranslation/DefaultGraphTranslationService.cs @@ -103,7 +103,11 @@ private IEnumerable GatherSetOfDetectedComponentsUnmerged(IEn // clone custom locations and make them relative to root. var declaredRawFilePaths = component.FilePaths ?? []; var componentCustomLocations = JsonConvert.DeserializeObject>(JsonConvert.SerializeObject(declaredRawFilePaths)); - component.FilePaths?.Clear(); + + if (updateLocations) + { + component.FilePaths?.Clear(); + } // Information about each component is relative to all of the graphs it is present in, so we take all graphs containing a given component and apply the graph data. foreach (var graphKvp in dependencyGraphsByLocation.Where(x => x.Value.Contains(component.Component.Id))) diff --git a/test/Microsoft.ComponentDetection.Orchestrator.Tests/Services/DefaultGraphTranslationServiceTests.cs b/test/Microsoft.ComponentDetection.Orchestrator.Tests/Services/DefaultGraphTranslationServiceTests.cs index b3ed0df1a..6979806f8 100644 --- a/test/Microsoft.ComponentDetection.Orchestrator.Tests/Services/DefaultGraphTranslationServiceTests.cs +++ b/test/Microsoft.ComponentDetection.Orchestrator.Tests/Services/DefaultGraphTranslationServiceTests.cs @@ -97,4 +97,73 @@ public void GenerateScanResultFromResult_WithCustomLocations() actualNpmComponent.Should().BeEquivalentTo(expectedNpmComponent); actualNugetComponent.Should().BeEquivalentTo(expectedNugetComponent); } + + [TestMethod] + public void GenerateScanResultFromResult_WithCustomLocations_WithExperimentsDryRun() + { + var detectedFilePath = "/some/file/path"; + var npmCustomPath = "/custom/path.js"; + var npmCustomPath2 = "D:/dummy/engtools/packages.lock.json"; + var nugetCustomPath = "/custom/path2.csproj"; + var relatedFilePath = "/generic/relevant/path"; + + var singleFileComponentRecorder = this.componentRecorder.CreateSingleFileComponentRecorder(Path.Join(this.sourceDirectory.FullName, detectedFilePath)); + var processingResult = new DetectorProcessingResult + { + ResultCode = ProcessingResultCode.Success, + ContainersDetailsMap = new Dictionary + { + { + this.sampleContainerDetails.Id, this.sampleContainerDetails + }, + }, + ComponentRecorders = [(this.componentDetectorMock.Object, this.componentRecorder)], + }; + + var expectedNpmComponent = new NpmComponent("npm-component", "1.2.3"); + var expectedNugetComponent = new NuGetComponent("nugetComponent", "4.5.6"); + var detectedNpmComponent = new DetectedComponent(expectedNpmComponent); + var detectedNugetComponent = new DetectedComponent(expectedNugetComponent); + + // Any Related File will be reported for ALL components found in this graph + singleFileComponentRecorder.AddAdditionalRelatedFile(Path.Join(this.sourceDirectory.FullName, relatedFilePath)); + + // Registering components in same manifest with different custom paths + detectedNpmComponent.AddComponentFilePath(Path.Join(this.sourceDirectory.FullName, npmCustomPath)); + detectedNpmComponent.AddComponentFilePath(npmCustomPath2); + detectedNugetComponent.AddComponentFilePath(Path.Join(this.sourceDirectory.FullName, nugetCustomPath)); + + singleFileComponentRecorder.RegisterUsage(detectedNpmComponent, isDevelopmentDependency: false); + singleFileComponentRecorder.RegisterUsage(detectedNugetComponent, isDevelopmentDependency: true); + + var settings = new ScanSettings + { + SourceDirectory = this.sourceDirectory, + }; + + // Experiments tool generates the graph but should not update the locations at all. + var result = this.serviceUnderTest.GenerateScanResultFromProcessingResult(processingResult, settings, updateLocations: false); + result.Should().NotBeNull(); + result.ComponentsFound.Should().HaveCount(2); + result.ResultCode.Should().Be(ProcessingResultCode.Success); + + // next run will record the actual locations from non-experimental detectors + result = this.serviceUnderTest.GenerateScanResultFromProcessingResult(processingResult, settings); + result.Should().NotBeNull(); + result.ComponentsFound.Should().HaveCount(2); + result.ResultCode.Should().Be(ProcessingResultCode.Success); + + var resultNpmComponent = result.ComponentsFound.Single(c => c.Component.Type == ComponentType.Npm); + var resultNugetComponent = result.ComponentsFound.Single(c => c.Component.Type == ComponentType.NuGet); + + // for now there is a bug that adds a forward slash to the path for symbolic links. This will be fixed in a future PR if we can parse dependency graph better for those. + resultNpmComponent.LocationsFoundAt.Should().BeEquivalentTo([npmCustomPath, detectedFilePath, relatedFilePath, $"/{npmCustomPath2}"]); + resultNugetComponent.LocationsFoundAt.Should().BeEquivalentTo([nugetCustomPath, detectedFilePath, relatedFilePath]); + + var actualNpmComponent = resultNpmComponent.Component as NpmComponent; + var actualNugetComponent = resultNugetComponent.Component as NuGetComponent; + + actualNpmComponent.Should().BeEquivalentTo(expectedNpmComponent); + actualNugetComponent.Should().BeEquivalentTo(expectedNugetComponent); + } } From 1a7b258a45b400accb4dbff8d9b719c56f9f6c90 Mon Sep 17 00:00:00 2001 From: Eric StJohn Date: Mon, 18 Nov 2024 15:45:01 -0800 Subject: [PATCH 07/10] Framework package updates (#1308) * Include non-implementation packages on .NETCore 2.x Microsoft.NETCore.App contains only reference assemblies, but it was listed in CVEs, so should be excluded. The same is true for System.Private.Uri. I did not include these previously because they weren't part of package overrides list, nor were they found through package comparisons - since conflict resolution doesn't need to do anything with non-implementation packages. They are important for CG though since they've been used in CVE reports. * Include framework packages for .NET 4.6.1 .NET 4.6.1 supports .NET Standard and has built in support for it that will win over nuget packages. In .NET 4.6.1 - .NET 4.7.1 this comes from the Microsoft.NET.Build.Extensions component, after that it's built into the framework itself. --- .../nuget/FrameworkPackages/FrameworkPackages.cs | 1 + .../FrameworkPackages.net461.cs | 16 ++++++++++++++++ .../FrameworkPackages.netcoreapp2.0.cs | 2 ++ .../FrameworkPackages.netcoreapp2.1.cs | 1 + 4 files changed, 20 insertions(+) create mode 100644 src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.net461.cs diff --git a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.cs b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.cs index cae44ea35..5d6a94a4f 100644 --- a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.cs +++ b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.cs @@ -23,6 +23,7 @@ static FrameworkPackages() { NETStandard20.Register(); NETStandard21.Register(); + NET461.Register(); NETCoreApp20.Register(); NETCoreApp21.Register(); NETCoreApp22.Register(); diff --git a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.net461.cs b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.net461.cs new file mode 100644 index 000000000..0d9214e5f --- /dev/null +++ b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.net461.cs @@ -0,0 +1,16 @@ +namespace Microsoft.ComponentDetection.Detectors.NuGet; + +using static global::NuGet.Frameworks.FrameworkConstants.CommonFrameworks; + +/// +/// Framework packages for .NETFramework,Version=v4.6.1. +/// +internal partial class FrameworkPackages +{ + internal static class NET461 + { + internal static FrameworkPackages Instance { get; } = new(Net461, DefaultFrameworkKey, NETStandard20.Instance); + + internal static void Register() => FrameworkPackages.Register(Instance); + } +} diff --git a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp2.0.cs b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp2.0.cs index fb029dcfe..69272e1ad 100644 --- a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp2.0.cs +++ b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp2.0.cs @@ -12,6 +12,7 @@ internal static class NETCoreApp20 internal static FrameworkPackages Instance { get; } = new(NetCoreApp20, FrameworkNames.NetCoreApp, NETStandard20.Instance) { { "Microsoft.CSharp", "4.4.0" }, + { "Microsoft.NETCore.App", "2.0.0" }, { "Microsoft.VisualBasic", "10.2.0" }, { "Microsoft.Win32.Registry", "4.4.0" }, { "runtime.any.System.Collections", "4.3.0" }, @@ -182,6 +183,7 @@ internal static class NETCoreApp20 { "System.Numerics.Vectors", "4.4.0" }, { "System.ObjectModel", "4.3.0" }, { "System.Private.DataContractSerialization", "4.3.0" }, + { "System.Private.Uri", "4.3.0" }, { "System.Reflection.DispatchProxy", "4.4.0" }, { "System.Reflection.Emit", "4.7.0" }, { "System.Reflection.Emit.ILGeneration", "4.7.0" }, diff --git a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp2.1.cs b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp2.1.cs index bd36be6d7..a046281fb 100644 --- a/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp2.1.cs +++ b/src/Microsoft.ComponentDetection.Detectors/nuget/FrameworkPackages/FrameworkPackages.netcoreapp2.1.cs @@ -12,6 +12,7 @@ internal static class NETCoreApp21 internal static FrameworkPackages Instance { get; } = new(NetCoreApp21, FrameworkNames.NetCoreApp, NETCoreApp20.Instance) { { "Microsoft.CSharp", "4.5.0" }, + { "Microsoft.NETCore.App", "2.1.0" }, { "Microsoft.VisualBasic", "10.3.0" }, { "Microsoft.Win32.Registry", "4.5.0" }, { "System.Buffers", "4.5.0" }, From 952c1ce221dd51a8c69dcb8c201ac5d0d94df178 Mon Sep 17 00:00:00 2001 From: Paul Dorsch <107068277+pauld-msft@users.noreply.github.com> Date: Tue, 19 Nov 2024 09:07:01 -0500 Subject: [PATCH 08/10] Update syft image and doc - use docker commands (#1307) * update syft doc * update syft output and image * bump linux container detector --- docs/update-syft.md | 39 ++- .../linux/Contracts/SyftOutput.cs | 252 +++++++++++++++--- .../linux/LinuxContainerDetector.cs | 2 +- .../linux/LinuxScanner.cs | 2 +- 4 files changed, 254 insertions(+), 41 deletions(-) diff --git a/docs/update-syft.md b/docs/update-syft.md index b2ce0b771..6ca4b6301 100644 --- a/docs/update-syft.md +++ b/docs/update-syft.md @@ -12,19 +12,40 @@ To do this: ``` 2. Find the [latest version of Syft][2] -3. Install [Skopeo][3] -4. Use [`skopeo`][4] to copy the manifest and images to our Azure Container Registry: +3. Pull the latest container image ``` - skopeo copy --all docker://docker.io/anchore/syft:{LATEST} docker://governancecontainerregistry.azurecr.io/syft:{LATEST} + $ docker pull docker.io/anchore/syft:v{LATEST} + v0.53.4: Pulling from anchore/syft + 0d60d5ab2113: Pull complete + 26136f3e3dd3: Pull complete + 497aa7f04842: Pull complete + Digest: sha256:37e85e8efdeaabb1b6f65c5bc175b664cb05d1aaddd0d922130b8e25d6e49726 + Status: Downloaded newer image for anchore/syft:v{LATEST} + docker.io/anchore/syft:v{LATEST} ``` -5. Update the container reference in [`LinuxScanner`][5] -6. Update [the models][6] that map the Syft output +4. Retag the container image + + ``` + $ docker tag docker.io/anchore/syft:v{LATEST} governancecontainerregistry.azurecr.io/syft:v{LATEST} + ``` + +5. Push the new image to the registry + + ``` + $ docker push governancecontainerregistry.azurecr.io/syft:v{LATEST} + The push refers to repository [governancecontainerregistry.azurecr.io/syft] + 9c858c120b14: Pushed + 840f3b941d62: Pushed + 21ce82bb7448: Pushed + v{LATEST}: digest: sha256:04ed9c717a814fdccf52758b67333632a0ff16840fc393f5fba5864285eaebbe size: 945 + ``` + +6. Update the container reference in [`LinuxScanner`][3] +7. Update [the models][4] that map the Syft output [1]: https://github.com/anchore/syft [2]: https://github.com/anchore/syft/releases/latest -[3]: https://github.com/containers/skopeo/blob/main/install.md -[4]: https://github.com/containers/skopeo -[5]: https://github.com/microsoft/component-detection/blob/aaf865e38112fb2448f5866ab06d5898358403f6/src/Microsoft.ComponentDetection.Detectors/linux/LinuxScanner.cs#L20 -[6]: https://github.com/microsoft/component-detection/blob/main/src/Microsoft.ComponentDetection.Detectors/linux/Contracts/SyftOutput.cs +[3]: https://github.com/microsoft/component-detection/blob/aaf865e38112fb2448f5866ab06d5898358403f6/src/Microsoft.ComponentDetection.Detectors/linux/LinuxScanner.cs#L20 +[4]: https://github.com/microsoft/component-detection/blob/main/src/Microsoft.ComponentDetection.Detectors/linux/Contracts/SyftOutput.cs diff --git a/src/Microsoft.ComponentDetection.Detectors/linux/Contracts/SyftOutput.cs b/src/Microsoft.ComponentDetection.Detectors/linux/Contracts/SyftOutput.cs index 5a2d93e11..c57168d18 100644 --- a/src/Microsoft.ComponentDetection.Detectors/linux/Contracts/SyftOutput.cs +++ b/src/Microsoft.ComponentDetection.Detectors/linux/Contracts/SyftOutput.cs @@ -30,7 +30,7 @@ public partial class ArtifactRelationshipElement public partial class ArtifactElement { - public string[] Cpes { get; set; } + public CpeElement[] Cpes { get; set; } public string FoundBy { get; set; } public string Id { get; set; } public string Language { get; set; } @@ -44,6 +44,12 @@ public partial class ArtifactElement public string Version { get; set; } } +public partial class CpeElement +{ + public string Cpe { get; set; } + public string Source { get; set; } +} + public partial class ArtifactLicense { public LocationElement[] Locations { get; set; } @@ -66,33 +72,40 @@ public partial class MetadataClass public string Architecture { get; set; } public BackupElement[] Backup { get; set; } public string Basepackage { get; set; } + public string[] Depends { get; set; } public string Description { get; set; } public File[] Files { get; set; } public string Package { get; set; } public string Packager { get; set; } + public string[] Provides { get; set; } public long? Reason { get; set; } public long? Size { get; set; } - public License? Url { get; set; } + public Checksum? Url { get; set; } public string Validation { get; set; } public string Version { get; set; } public string GitCommitOfApkPort { get; set; } public long? InstalledSize { get; set; } public string Maintainer { get; set; } public string OriginPackage { get; set; } - public string[] Provides { get; set; } public string PullChecksum { get; set; } public string[] PullDependencies { get; set; } public MatchElement[] Matches { get; set; } public string Ref { get; set; } - public string PackageId { get; set; } + public string SyftOutpuPackageId { get; set; } public string[] BuildRequires { get; set; } public string Context { get; set; } - public Dictionary Options { get; set; } + public GoBuildSettingElement[] Options { get; set; } public string Path { get; set; } public string Prev { get; set; } public string[] PyRequires { get; set; } public string[] Requires { get; set; } - public string Checksum { get; set; } + public string Channel { get; set; } + public string PackageId { get; set; } + public string PackageRevision { get; set; } + public string RecipeRevision { get; set; } + public string Timestamp { get; set; } + public string Username { get; set; } + public Checksum? Checksum { get; set; } public string HostedUrl { get; set; } public string Name { get; set; } public string VcsUrl { get; set; } @@ -105,15 +118,23 @@ public partial class MetadataClass public string LegalCopyright { get; set; } public string ProductName { get; set; } public string ProductVersion { get; set; } - public string[] Depends { get; set; } public string[] PreDepends { get; set; } public SourceUnion? Source { get; set; } public string SourceVersion { get; set; } + public string Commit { get; set; } + public string Os { get; set; } + public string OsCpe { get; set; } + public string OsVersion { get; set; } + public string SourceRepo { get; set; } + public string System { get; set; } + public string Type { get; set; } + public string Vendor { get; set; } public string PkgHash { get; set; } public string PkgHashExt { get; set; } - public Dictionary GoBuildSettings { get; set; } + public GoBuildSettingElement[] GoBuildSettings { get; set; } public string GoCompiledVersion { get; set; } public string[] GoCryptoSettings { get; set; } + public string[] GoExperiments { get; set; } public string H1Digest { get; set; } public string MainModule { get; set; } public string SnapshotUrl { get; set; } @@ -122,6 +143,7 @@ public partial class MetadataClass public PomProject PomProject { get; set; } public PomProperties PomProperties { get; set; } public string VirtualPath { get; set; } + public ReleaseUnion? Release { get; set; } public string Author { get; set; } public string Homepage { get; set; } public bool? Private { get; set; } @@ -135,13 +157,15 @@ public partial class MetadataClass public long? SwapDevice { get; set; } public string VideoMode { get; set; } public string KernelVersion { get; set; } - public License? License { get; set; } + public Checksum? License { get; set; } public Dictionary Parameters { get; set; } public string VersionMagic { get; set; } + public Dependencies? Dependencies { get; set; } public string Kb { get; set; } public string ProductId { get; set; } public string Output { get; set; } public string OutputHash { get; set; } + public string[] Licenses { get; set; } public Author[] Authors { get; set; } public string[] Bin { get; set; } public Dist Dist { get; set; } @@ -152,13 +176,15 @@ public partial class MetadataClass public Dictionary RequireDev { get; set; } public Dictionary Suggest { get; set; } public string Time { get; set; } - public string Type { get; set; } public string AuthorEmail { get; set; } public DirectUrlOrigin DirectUrlOrigin { get; set; } public string Platform { get; set; } + public string[] ProvidesExtra { get; set; } + public string[] RequiresDist { get; set; } + public string RequiresPython { get; set; } public string SitePackagesRootPath { get; set; } public string[] TopLevelPackages { get; set; } - public string[] Extras { get; set; } + public Extra[] Extras { get; set; } public string Markers { get; set; } public string VersionConstraint { get; set; } public string[] Hashes { get; set; } @@ -171,11 +197,11 @@ public partial class MetadataClass public string Title { get; set; } public long? Epoch { get; set; } public string ModularityLabel { get; set; } - public string Release { get; set; } public string SourceRpm { get; set; } - public string Vendor { get; set; } - public string[] Dependencies { get; set; } public string Revision { get; set; } + public string PackagerEmail { get; set; } + public string AuthorUri { get; set; } + public string PluginInstallDirectory { get; set; } } public partial class AuthorClass @@ -203,6 +229,15 @@ public partial class DigestElement public string Value { get; set; } } +public partial class DependencyClass +{ + public string[] Extras { get; set; } + public string Markers { get; set; } + public string Name { get; set; } + public bool Optional { get; set; } + public string Version { get; set; } +} + public partial class DirectUrlOrigin { public string CommitId { get; set; } @@ -218,6 +253,12 @@ public partial class Dist public string Url { get; set; } } +public partial class ExtraClass +{ + public string[] Dependencies { get; set; } + public string Name { get; set; } +} + public partial class FileFile { public Digest? Digest { get; set; } @@ -244,10 +285,16 @@ public partial class PurpleSyftOutpu public string Value { get; set; } } +public partial class GoBuildSettingElement +{ + public string Key { get; set; } + public string Value { get; set; } +} + public partial class Manifest { - public Dictionary Main { get; set; } - public Dictionary> NamedSections { get; set; } + public GoBuildSettingElement[] Main { get; set; } + public GoBuildSettingElement[][] Sections { get; set; } } public partial class MatchElement @@ -292,6 +339,31 @@ public partial class PomProperties public string Version { get; set; } } +public partial class ReleaseClass +{ + public string BuildInfo { get; set; } + public string BuildSource { get; set; } + public string BuildSourceRepo { get; set; } + public string BuildType { get; set; } + public string FullVersion { get; set; } + public string ImageType { get; set; } + public string Implementor { get; set; } + public string ImplementorVersion { get; set; } + public string JavaRuntimeVersion { get; set; } + public string JavaVersion { get; set; } + public string JavaVersionDate { get; set; } + public string JvmVariant { get; set; } + public string JvmVersion { get; set; } + public string Libc { get; set; } + public string[] Modules { get; set; } + public string OsArch { get; set; } + public string OsName { get; set; } + public string OsVersion { get; set; } + public string SemanticVersion { get; set; } + public string Source { get; set; } + public string SourceRepo { get; set; } +} + public partial class Descriptor { public object Configuration { get; set; } @@ -325,10 +397,34 @@ public partial class FileElement { public string Contents { get; set; } public DigestElement[] Digests { get; set; } + public Executable Executable { get; set; } public string Id { get; set; } public FileLicense[] Licenses { get; set; } public Location Location { get; set; } public Metadata Metadata { get; set; } + public string[] Unknowns { get; set; } +} + +public partial class Executable +{ + public ElfSecurityFeatures ElfSecurityFeatures { get; set; } + public string Format { get; set; } + public bool HasEntrypoint { get; set; } + public bool HasExports { get; set; } + public string[] ImportedLibraries { get; set; } +} + +public partial class ElfSecurityFeatures +{ + public bool? Cfi { get; set; } + public bool Dso { get; set; } + public bool? Fortify { get; set; } + public bool Nx { get; set; } + public bool Pie { get; set; } + public string RelRo { get; set; } + public bool? SafeStack { get; set; } + public bool? StackCanary { get; set; } + public bool SymbolTableStripped { get; set; } } public partial class FileLicense @@ -383,8 +479,74 @@ public partial struct Author public AuthorClass AuthorClass; public string String; - public static implicit operator Author(AuthorClass AuthorClass) => new Author { AuthorClass = AuthorClass }; - public static implicit operator Author(string String) => new Author { String = String }; + public static implicit operator Author(AuthorClass AuthorClass) + { + return new Author { AuthorClass = AuthorClass }; + } + public static implicit operator Author(string String) + { + return new Author { String = String }; + } +} + +public partial struct Checksum +{ + public string String; + public string[] StringArray; + + public static implicit operator Checksum(string String) + { + return new Checksum { String = String }; + } + public static implicit operator Checksum(string[] StringArray) + { + return new Checksum { StringArray = StringArray }; + } +} + +public partial struct Dependency +{ + public DependencyClass DependencyClass; + public string String; + + public static implicit operator Dependency(DependencyClass DependencyClass) + { + return new Dependency { DependencyClass = DependencyClass }; + } + public static implicit operator Dependency(string String) + { + return new Dependency { String = String }; + } +} + +public partial struct Dependencies +{ + public Dependency[] AnythingArray; + public Dictionary StringMap; + + public static implicit operator Dependencies(Dependency[] AnythingArray) + { + return new Dependencies { AnythingArray = AnythingArray }; + } + public static implicit operator Dependencies(Dictionary StringMap) + { + return new Dependencies { StringMap = StringMap }; + } +} + +public partial struct Extra +{ + public ExtraClass ExtraClass; + public string String; + + public static implicit operator Extra(ExtraClass ExtraClass) + { + return new Extra { ExtraClass = ExtraClass }; + } + public static implicit operator Extra(string String) + { + return new Extra { String = String }; + } } public partial struct Digest @@ -392,8 +554,14 @@ public partial struct Digest public DigestElement[] DigestElementArray; public PurpleSyftOutpu PurpleSyftOutpu; - public static implicit operator Digest(DigestElement[] DigestElementArray) => new Digest { DigestElementArray = DigestElementArray }; - public static implicit operator Digest(PurpleSyftOutpu PurpleSyftOutpu) => new Digest { PurpleSyftOutpu = PurpleSyftOutpu }; + public static implicit operator Digest(DigestElement[] DigestElementArray) + { + return new Digest { DigestElementArray = DigestElementArray }; + } + public static implicit operator Digest(PurpleSyftOutpu PurpleSyftOutpu) + { + return new Digest { PurpleSyftOutpu = PurpleSyftOutpu }; + } } public partial struct Size @@ -401,8 +569,14 @@ public partial struct Size public long? Integer; public string String; - public static implicit operator Size(long Integer) => new Size { Integer = Integer }; - public static implicit operator Size(string String) => new Size { String = String }; + public static implicit operator Size(long Integer) + { + return new Size { Integer = Integer }; + } + public static implicit operator Size(string String) + { + return new Size { String = String }; + } } public partial struct File @@ -410,17 +584,29 @@ public partial struct File public FileFile FileFile; public string String; - public static implicit operator File(FileFile FileFile) => new File { FileFile = FileFile }; - public static implicit operator File(string String) => new File { String = String }; + public static implicit operator File(FileFile FileFile) + { + return new File { FileFile = FileFile }; + } + public static implicit operator File(string String) + { + return new File { String = String }; + } } -public partial struct License +public partial struct ReleaseUnion { + public ReleaseClass ReleaseClass; public string String; - public string[] StringArray; - public static implicit operator License(string String) => new License { String = String }; - public static implicit operator License(string[] StringArray) => new License { StringArray = StringArray }; + public static implicit operator ReleaseUnion(ReleaseClass ReleaseClass) + { + return new ReleaseUnion { ReleaseClass = ReleaseClass }; + } + public static implicit operator ReleaseUnion(string String) + { + return new ReleaseUnion { String = String }; + } } public partial struct SourceUnion @@ -428,6 +614,12 @@ public partial struct SourceUnion public Dist Dist; public string String; - public static implicit operator SourceUnion(Dist Dist) => new SourceUnion { Dist = Dist }; - public static implicit operator SourceUnion(string String) => new SourceUnion { String = String }; + public static implicit operator SourceUnion(Dist Dist) + { + return new SourceUnion { Dist = Dist }; + } + public static implicit operator SourceUnion(string String) + { + return new SourceUnion { String = String }; + } } diff --git a/src/Microsoft.ComponentDetection.Detectors/linux/LinuxContainerDetector.cs b/src/Microsoft.ComponentDetection.Detectors/linux/LinuxContainerDetector.cs index fcd655ba2..5822cfa54 100644 --- a/src/Microsoft.ComponentDetection.Detectors/linux/LinuxContainerDetector.cs +++ b/src/Microsoft.ComponentDetection.Detectors/linux/LinuxContainerDetector.cs @@ -35,7 +35,7 @@ public LinuxContainerDetector(ILinuxScanner linuxScanner, IDockerService dockerS public IEnumerable SupportedComponentTypes => [ComponentType.Linux]; - public int Version => 4; + public int Version => 5; public bool NeedsAutomaticRootDependencyCalculation => false; diff --git a/src/Microsoft.ComponentDetection.Detectors/linux/LinuxScanner.cs b/src/Microsoft.ComponentDetection.Detectors/linux/LinuxScanner.cs index e49cfc038..2c9b1fd23 100644 --- a/src/Microsoft.ComponentDetection.Detectors/linux/LinuxScanner.cs +++ b/src/Microsoft.ComponentDetection.Detectors/linux/LinuxScanner.cs @@ -15,7 +15,7 @@ namespace Microsoft.ComponentDetection.Detectors.Linux; public class LinuxScanner : ILinuxScanner { - private const string ScannerImage = "governancecontainerregistry.azurecr.io/syft:v0.100.0@sha256:df7b07bfadff45e0135d74f22478f47b16ac6aff4e8dbd93133fcae3bbbb790d"; + private const string ScannerImage = "governancecontainerregistry.azurecr.io/syft:v1.16.0@sha256:12774e791a2b2bc48935c73da15180eee7f31815bc978b14f8f85cc408ec960b"; private static readonly IList CmdParameters = [ From 218b6933aca2a1c4c8f84647387d2c25bcd93918 Mon Sep 17 00:00:00 2001 From: Greg Villicana <58237075+grvillic@users.noreply.github.com> Date: Mon, 2 Dec 2024 09:12:29 -0800 Subject: [PATCH 09/10] Fix Experiments evaluation of new dep dependencies (#1315) * Fix Experiments evaluation of new dep dependencies --- .../Experiments/Models/ExperimentDiff.cs | 19 ++++++++++++--- .../Experiments/ExperimentDiffTests.cs | 23 +++++++++++++++++++ 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.ComponentDetection.Orchestrator/Experiments/Models/ExperimentDiff.cs b/src/Microsoft.ComponentDetection.Orchestrator/Experiments/Models/ExperimentDiff.cs index e0fe879eb..16d9eafc0 100644 --- a/src/Microsoft.ComponentDetection.Orchestrator/Experiments/Models/ExperimentDiff.cs +++ b/src/Microsoft.ComponentDetection.Orchestrator/Experiments/Models/ExperimentDiff.cs @@ -40,10 +40,23 @@ public ExperimentDiff( var experimentDetectorList = new List(); // Need performance benchmark to see if this is worth parallelization - foreach (var id in newComponentDictionary.Keys.Intersect(oldComponentDictionary.Keys)) + foreach (var newComponentPair in newComponentDictionary) { - var oldComponent = oldComponentDictionary[id]; - var newComponent = newComponentDictionary[id]; + var newComponent = newComponentPair.Value; + var id = newComponentPair.Key; + + if (!oldComponentDictionary.TryGetValue(id, out var oldComponent)) + { + if (newComponent.DevelopmentDependency) + { + developmentDependencyChanges.Add(new DevelopmentDependencyChange( + id, + oldValue: false, + newValue: newComponent.DevelopmentDependency)); + } + + continue; + } if (oldComponent.DevelopmentDependency != newComponent.DevelopmentDependency) { diff --git a/test/Microsoft.ComponentDetection.Orchestrator.Tests/Experiments/ExperimentDiffTests.cs b/test/Microsoft.ComponentDetection.Orchestrator.Tests/Experiments/ExperimentDiffTests.cs index f1a1fffcd..d5d2c4dec 100644 --- a/test/Microsoft.ComponentDetection.Orchestrator.Tests/Experiments/ExperimentDiffTests.cs +++ b/test/Microsoft.ComponentDetection.Orchestrator.Tests/Experiments/ExperimentDiffTests.cs @@ -139,4 +139,27 @@ public void ExperimentDiff_MultipleIds_ShouldntThrow() action.Should().NotThrow(); } + + [TestMethod] + public void ExperimentDiff_DiffsAddedDevDependenciesMissingInControlGroup() + { + var componentA = ExperimentTestUtils.CreateRandomScannedComponent(); + componentA.IsDevelopmentDependency = true; + + var diff = new ExperimentDiff( + [], + [new ExperimentComponent(componentA)]); + + diff.DevelopmentDependencyChanges.Should().ContainSingle(); + + var change = diff.DevelopmentDependencyChanges.First(); + change.Id.Should().Be(componentA.Component.Id); + change.OldValue.Should().BeFalse(); + change.NewValue.Should().BeTrue(); + + diff.AddedIds.Should().BeEquivalentTo([componentA.Component.Id]); + diff.RemovedIds.Should().BeEmpty(); + diff.AddedRootIds.Should().BeEmpty(); + diff.RemovedRootIds.Should().BeEmpty(); + } } From 9f24dfc09a427fd6ff3c3932856f2b85e81bc3d1 Mon Sep 17 00:00:00 2001 From: Fernando Rojo Date: Mon, 2 Dec 2024 12:21:00 -0800 Subject: [PATCH 10/10] Introduce pnpm lockfile v9 detector (#1283) * Introduce pnpm lockfile v9 detector * Fix test build * Add tests and update comments * Update version * coverage update * requeue PR builds * Fix smoke test --------- Co-authored-by: Greg Villicana <58237075+grvillic@users.noreply.github.com> --- .../{PnpmYamlVersion.cs => PnpmYaml.cs} | 5 +- .../pnpm/Contracts/PnpmYamlV5.cs | 5 +- .../{ => V6}/PnpmHasDependenciesV6.cs | 2 +- .../pnpm/Contracts/{ => V6}/PnpmYamlV6.cs | 3 - .../{ => V6}/PnpmYamlV6Dependency.cs | 0 .../Contracts/V9/PnpmHasDependenciesV9.cs | 16 ++ .../pnpm/Contracts/V9/PnpmYamlV9.cs | 21 ++ .../pnpm/Contracts/V9/PnpmYamlV9Dependency.cs | 9 + .../pnpm/IPnpmDetector.cs | 10 + .../PnpmParsingUtilitiesBase.cs | 52 +++++ .../PnpmParsingUtilitiesFactory.cs | 27 +++ .../PnpmV5ParsingUtilities.cs | 58 +++++ .../PnpmV6ParsingUtilities.cs | 42 ++++ .../PnpmV9ParsingUtilities.cs | 54 +++++ .../pnpm/Pnpm5Detector.cs | 22 +- .../pnpm/Pnpm6Detector.cs | 17 +- .../pnpm/Pnpm9Detector.cs | 114 +++++++++ .../pnpm/PnpmComponentDetectorFactory.cs | 7 +- .../pnpm/PnpmParsingUtilities.cs | 167 ------------- .../PnpmDetectorTests.cs | 220 +++++++++++++++++- .../PnpmParsingUtilitiesTest.cs | 55 +++-- 21 files changed, 681 insertions(+), 225 deletions(-) rename src/Microsoft.ComponentDetection.Detectors/pnpm/Contracts/{PnpmYamlVersion.cs => PnpmYaml.cs} (58%) rename src/Microsoft.ComponentDetection.Detectors/pnpm/Contracts/{ => V6}/PnpmHasDependenciesV6.cs (91%) rename src/Microsoft.ComponentDetection.Detectors/pnpm/Contracts/{ => V6}/PnpmYamlV6.cs (89%) rename src/Microsoft.ComponentDetection.Detectors/pnpm/Contracts/{ => V6}/PnpmYamlV6Dependency.cs (100%) create mode 100644 src/Microsoft.ComponentDetection.Detectors/pnpm/Contracts/V9/PnpmHasDependenciesV9.cs create mode 100644 src/Microsoft.ComponentDetection.Detectors/pnpm/Contracts/V9/PnpmYamlV9.cs create mode 100644 src/Microsoft.ComponentDetection.Detectors/pnpm/Contracts/V9/PnpmYamlV9Dependency.cs create mode 100644 src/Microsoft.ComponentDetection.Detectors/pnpm/ParsingUtilities/PnpmParsingUtilitiesBase.cs create mode 100644 src/Microsoft.ComponentDetection.Detectors/pnpm/ParsingUtilities/PnpmParsingUtilitiesFactory.cs create mode 100644 src/Microsoft.ComponentDetection.Detectors/pnpm/ParsingUtilities/PnpmV5ParsingUtilities.cs create mode 100644 src/Microsoft.ComponentDetection.Detectors/pnpm/ParsingUtilities/PnpmV6ParsingUtilities.cs create mode 100644 src/Microsoft.ComponentDetection.Detectors/pnpm/ParsingUtilities/PnpmV9ParsingUtilities.cs create mode 100644 src/Microsoft.ComponentDetection.Detectors/pnpm/Pnpm9Detector.cs delete mode 100644 src/Microsoft.ComponentDetection.Detectors/pnpm/PnpmParsingUtilities.cs diff --git a/src/Microsoft.ComponentDetection.Detectors/pnpm/Contracts/PnpmYamlVersion.cs b/src/Microsoft.ComponentDetection.Detectors/pnpm/Contracts/PnpmYaml.cs similarity index 58% rename from src/Microsoft.ComponentDetection.Detectors/pnpm/Contracts/PnpmYamlVersion.cs rename to src/Microsoft.ComponentDetection.Detectors/pnpm/Contracts/PnpmYaml.cs index 2ceb4ffc3..8ce9c4e56 100644 --- a/src/Microsoft.ComponentDetection.Detectors/pnpm/Contracts/PnpmYamlVersion.cs +++ b/src/Microsoft.ComponentDetection.Detectors/pnpm/Contracts/PnpmYaml.cs @@ -2,7 +2,10 @@ namespace Microsoft.ComponentDetection.Detectors.Pnpm; using YamlDotNet.Serialization; -public class PnpmYamlVersion +/// +/// Base class for all Pnpm lockfiles. Used for parsing the lockfile version. +/// +public class PnpmYaml { [YamlMember(Alias = "lockfileVersion")] public string LockfileVersion { get; set; } diff --git a/src/Microsoft.ComponentDetection.Detectors/pnpm/Contracts/PnpmYamlV5.cs b/src/Microsoft.ComponentDetection.Detectors/pnpm/Contracts/PnpmYamlV5.cs index 47f031a9b..d9fbe9a6f 100644 --- a/src/Microsoft.ComponentDetection.Detectors/pnpm/Contracts/PnpmYamlV5.cs +++ b/src/Microsoft.ComponentDetection.Detectors/pnpm/Contracts/PnpmYamlV5.cs @@ -6,14 +6,11 @@ namespace Microsoft.ComponentDetection.Detectors.Pnpm; /// /// Format for a Pnpm lock file version 5 as defined in https://github.com/pnpm/spec/blob/master/lockfile/5.md. /// -public class PnpmYamlV5 +public class PnpmYamlV5 : PnpmYaml { [YamlMember(Alias = "dependencies")] public Dictionary Dependencies { get; set; } [YamlMember(Alias = "packages")] public Dictionary Packages { get; set; } - - [YamlMember(Alias = "lockfileVersion")] - public string LockfileVersion { get; set; } } diff --git a/src/Microsoft.ComponentDetection.Detectors/pnpm/Contracts/PnpmHasDependenciesV6.cs b/src/Microsoft.ComponentDetection.Detectors/pnpm/Contracts/V6/PnpmHasDependenciesV6.cs similarity index 91% rename from src/Microsoft.ComponentDetection.Detectors/pnpm/Contracts/PnpmHasDependenciesV6.cs rename to src/Microsoft.ComponentDetection.Detectors/pnpm/Contracts/V6/PnpmHasDependenciesV6.cs index e04135aa2..c1fd6891d 100644 --- a/src/Microsoft.ComponentDetection.Detectors/pnpm/Contracts/PnpmHasDependenciesV6.cs +++ b/src/Microsoft.ComponentDetection.Detectors/pnpm/Contracts/V6/PnpmHasDependenciesV6.cs @@ -3,7 +3,7 @@ namespace Microsoft.ComponentDetection.Detectors.Pnpm; using System.Collections.Generic; using YamlDotNet.Serialization; -public class PnpmHasDependenciesV6 +public class PnpmHasDependenciesV6 : PnpmYaml { [YamlMember(Alias = "dependencies")] public Dictionary Dependencies { get; set; } diff --git a/src/Microsoft.ComponentDetection.Detectors/pnpm/Contracts/PnpmYamlV6.cs b/src/Microsoft.ComponentDetection.Detectors/pnpm/Contracts/V6/PnpmYamlV6.cs similarity index 89% rename from src/Microsoft.ComponentDetection.Detectors/pnpm/Contracts/PnpmYamlV6.cs rename to src/Microsoft.ComponentDetection.Detectors/pnpm/Contracts/V6/PnpmYamlV6.cs index d9ca7bbf4..f71768081 100644 --- a/src/Microsoft.ComponentDetection.Detectors/pnpm/Contracts/PnpmYamlV6.cs +++ b/src/Microsoft.ComponentDetection.Detectors/pnpm/Contracts/V6/PnpmYamlV6.cs @@ -17,7 +17,4 @@ public class PnpmYamlV6 : PnpmHasDependenciesV6 [YamlMember(Alias = "packages")] public Dictionary Packages { get; set; } - - [YamlMember(Alias = "lockfileVersion")] - public string LockfileVersion { get; set; } } diff --git a/src/Microsoft.ComponentDetection.Detectors/pnpm/Contracts/PnpmYamlV6Dependency.cs b/src/Microsoft.ComponentDetection.Detectors/pnpm/Contracts/V6/PnpmYamlV6Dependency.cs similarity index 100% rename from src/Microsoft.ComponentDetection.Detectors/pnpm/Contracts/PnpmYamlV6Dependency.cs rename to src/Microsoft.ComponentDetection.Detectors/pnpm/Contracts/V6/PnpmYamlV6Dependency.cs diff --git a/src/Microsoft.ComponentDetection.Detectors/pnpm/Contracts/V9/PnpmHasDependenciesV9.cs b/src/Microsoft.ComponentDetection.Detectors/pnpm/Contracts/V9/PnpmHasDependenciesV9.cs new file mode 100644 index 000000000..ebb91a305 --- /dev/null +++ b/src/Microsoft.ComponentDetection.Detectors/pnpm/Contracts/V9/PnpmHasDependenciesV9.cs @@ -0,0 +1,16 @@ +namespace Microsoft.ComponentDetection.Detectors.Pnpm; + +using System.Collections.Generic; +using YamlDotNet.Serialization; + +public class PnpmHasDependenciesV9 : PnpmYaml +{ + [YamlMember(Alias = "dependencies")] + public Dictionary Dependencies { get; set; } + + [YamlMember(Alias = "devDependencies")] + public Dictionary DevDependencies { get; set; } + + [YamlMember(Alias = "optionalDependencies")] + public Dictionary OptionalDependencies { get; set; } +} diff --git a/src/Microsoft.ComponentDetection.Detectors/pnpm/Contracts/V9/PnpmYamlV9.cs b/src/Microsoft.ComponentDetection.Detectors/pnpm/Contracts/V9/PnpmYamlV9.cs new file mode 100644 index 000000000..44e077ee2 --- /dev/null +++ b/src/Microsoft.ComponentDetection.Detectors/pnpm/Contracts/V9/PnpmYamlV9.cs @@ -0,0 +1,21 @@ +namespace Microsoft.ComponentDetection.Detectors.Pnpm; + +using System.Collections.Generic; +using YamlDotNet.Serialization; + +/// +/// There is still no official docs for the new v9 lock if format, so these parsing contracts are empirically based. +/// Issue tracking v9 specs: https://github.com/pnpm/spec/issues/6 +/// Format should eventually get updated here: https://github.com/pnpm/spec/blob/master/lockfile/6.0.md. +/// +public class PnpmYamlV9 : PnpmHasDependenciesV9 +{ + [YamlMember(Alias = "importers")] + public Dictionary Importers { get; set; } + + [YamlMember(Alias = "packages")] + public Dictionary Packages { get; set; } + + [YamlMember(Alias = "snapshots")] + public Dictionary Snapshots { get; set; } +} diff --git a/src/Microsoft.ComponentDetection.Detectors/pnpm/Contracts/V9/PnpmYamlV9Dependency.cs b/src/Microsoft.ComponentDetection.Detectors/pnpm/Contracts/V9/PnpmYamlV9Dependency.cs new file mode 100644 index 000000000..eb7c35e07 --- /dev/null +++ b/src/Microsoft.ComponentDetection.Detectors/pnpm/Contracts/V9/PnpmYamlV9Dependency.cs @@ -0,0 +1,9 @@ +namespace Microsoft.ComponentDetection.Detectors.Pnpm; + +using YamlDotNet.Serialization; + +public class PnpmYamlV9Dependency +{ + [YamlMember(Alias = "version")] + public string Version { get; set; } +} diff --git a/src/Microsoft.ComponentDetection.Detectors/pnpm/IPnpmDetector.cs b/src/Microsoft.ComponentDetection.Detectors/pnpm/IPnpmDetector.cs index 4c2695dc3..7557c76b3 100644 --- a/src/Microsoft.ComponentDetection.Detectors/pnpm/IPnpmDetector.cs +++ b/src/Microsoft.ComponentDetection.Detectors/pnpm/IPnpmDetector.cs @@ -14,3 +14,13 @@ public interface IPnpmDetector /// Component recorder to which to write the dependency graph. public void RecordDependencyGraphFromFile(string yamlFileContent, ISingleFileComponentRecorder singleFileComponentRecorder); } + +/// +/// Constants used in Pnpm Detectors. +/// +public static class PnpmConstants +{ + public const string PnpmFileDependencyPath = "file:"; + + public const string PnpmLinkDependencyPath = "link:"; +} diff --git a/src/Microsoft.ComponentDetection.Detectors/pnpm/ParsingUtilities/PnpmParsingUtilitiesBase.cs b/src/Microsoft.ComponentDetection.Detectors/pnpm/ParsingUtilities/PnpmParsingUtilitiesBase.cs new file mode 100644 index 000000000..fbda4d291 --- /dev/null +++ b/src/Microsoft.ComponentDetection.Detectors/pnpm/ParsingUtilities/PnpmParsingUtilitiesBase.cs @@ -0,0 +1,52 @@ +namespace Microsoft.ComponentDetection.Detectors.Pnpm; + +using System; +using System.Collections.Generic; +using System.IO; +using Microsoft.ComponentDetection.Contracts; +using YamlDotNet.Serialization; + +public abstract class PnpmParsingUtilitiesBase +where T : PnpmYaml +{ + public T DeserializePnpmYamlFile(string fileContent) + { + var deserializer = new DeserializerBuilder() + .IgnoreUnmatchedProperties() + .Build(); + return deserializer.Deserialize(new StringReader(fileContent)); + } + + public virtual bool IsPnpmPackageDevDependency(Package pnpmPackage) + { + ArgumentNullException.ThrowIfNull(pnpmPackage); + + return string.Equals(bool.TrueString, pnpmPackage.Dev, StringComparison.InvariantCultureIgnoreCase); + } + + public bool IsLocalDependency(KeyValuePair dependency) + { + // Local dependencies are dependencies that live in the file system + // this requires an extra parsing that is not supported yet + return dependency.Key.StartsWith(PnpmConstants.PnpmFileDependencyPath) || dependency.Value.StartsWith(PnpmConstants.PnpmFileDependencyPath) || dependency.Value.StartsWith(PnpmConstants.PnpmLinkDependencyPath); + } + + /// + /// Parse a pnpm path of the form "/package-name/version". + /// + /// a pnpm path of the form "/package-name/version". + /// Data parsed from path. + public abstract DetectedComponent CreateDetectedComponentFromPnpmPath(string pnpmPackagePath); + + public virtual string ReconstructPnpmDependencyPath(string dependencyName, string dependencyVersion) + { + if (dependencyVersion.StartsWith('/')) + { + return dependencyVersion; + } + else + { + return $"/{dependencyName}@{dependencyVersion}"; + } + } +} diff --git a/src/Microsoft.ComponentDetection.Detectors/pnpm/ParsingUtilities/PnpmParsingUtilitiesFactory.cs b/src/Microsoft.ComponentDetection.Detectors/pnpm/ParsingUtilities/PnpmParsingUtilitiesFactory.cs new file mode 100644 index 000000000..4e0c015bf --- /dev/null +++ b/src/Microsoft.ComponentDetection.Detectors/pnpm/ParsingUtilities/PnpmParsingUtilitiesFactory.cs @@ -0,0 +1,27 @@ +namespace Microsoft.ComponentDetection.Detectors.Pnpm; + +using System.IO; +using YamlDotNet.Serialization; + +public static class PnpmParsingUtilitiesFactory +{ + public static PnpmParsingUtilitiesBase Create() + where T : PnpmYaml + { + return typeof(T).Name switch + { + nameof(PnpmYamlV5) => new PnpmV5ParsingUtilities(), + nameof(PnpmYamlV6) => new PnpmV6ParsingUtilities(), + nameof(PnpmYamlV9) => new PnpmV9ParsingUtilities(), + _ => new PnpmV5ParsingUtilities(), + }; + } + + public static string DeserializePnpmYamlFileVersion(string fileContent) + { + var deserializer = new DeserializerBuilder() + .IgnoreUnmatchedProperties() + .Build(); + return deserializer.Deserialize(new StringReader(fileContent))?.LockfileVersion; + } +} diff --git a/src/Microsoft.ComponentDetection.Detectors/pnpm/ParsingUtilities/PnpmV5ParsingUtilities.cs b/src/Microsoft.ComponentDetection.Detectors/pnpm/ParsingUtilities/PnpmV5ParsingUtilities.cs new file mode 100644 index 000000000..02015c288 --- /dev/null +++ b/src/Microsoft.ComponentDetection.Detectors/pnpm/ParsingUtilities/PnpmV5ParsingUtilities.cs @@ -0,0 +1,58 @@ +namespace Microsoft.ComponentDetection.Detectors.Pnpm; + +using System.Linq; +using global::NuGet.Versioning; +using Microsoft.ComponentDetection.Contracts; +using Microsoft.ComponentDetection.Contracts.TypedComponent; + +public class PnpmV5ParsingUtilities : PnpmParsingUtilitiesBase +where T : PnpmYaml +{ + public override DetectedComponent CreateDetectedComponentFromPnpmPath(string pnpmPackagePath) + { + var (parentName, parentVersion) = this.ExtractNameAndVersionFromPnpmPackagePath(pnpmPackagePath); + return new DetectedComponent(new NpmComponent(parentName, parentVersion)); + } + + private (string Name, string Version) ExtractNameAndVersionFromPnpmPackagePath(string pnpmPackagePath) + { + var pnpmComponentDefSections = pnpmPackagePath.Trim('/').Split('/'); + (var packageVersion, var indexVersionIsAt) = this.GetPackageVersion(pnpmComponentDefSections); + if (indexVersionIsAt == -1) + { + // No version = not expected input + return (null, null); + } + + var normalizedPackageName = string.Join("/", pnpmComponentDefSections.Take(indexVersionIsAt).ToArray()); + return (normalizedPackageName, packageVersion); + } + + private (string PackageVersion, int VersionIndex) GetPackageVersion(string[] pnpmComponentDefSections) + { + var indexVersionIsAt = -1; + var packageVersion = string.Empty; + var lastIndex = pnpmComponentDefSections.Length - 1; + + // get version from packages with format /mute-stream/0.0.6 + if (SemanticVersion.TryParse(pnpmComponentDefSections[lastIndex], out var _)) + { + return (pnpmComponentDefSections[lastIndex], lastIndex); + } + + // get version from packages with format /@babel/helper-compilation-targets/7.10.4_@babel+core@7.10.5 + var lastComponentSplit = pnpmComponentDefSections[lastIndex].Split("_"); + if (SemanticVersion.TryParse(lastComponentSplit[0], out var _)) + { + return (lastComponentSplit[0], lastIndex); + } + + // get version from packages with format /sinon-chai/2.8.0/chai@3.5.0+sinon@1.17.7 + if (SemanticVersion.TryParse(pnpmComponentDefSections[lastIndex - 1], out var _)) + { + return (pnpmComponentDefSections[lastIndex - 1], lastIndex - 1); + } + + return (packageVersion, indexVersionIsAt); + } +} diff --git a/src/Microsoft.ComponentDetection.Detectors/pnpm/ParsingUtilities/PnpmV6ParsingUtilities.cs b/src/Microsoft.ComponentDetection.Detectors/pnpm/ParsingUtilities/PnpmV6ParsingUtilities.cs new file mode 100644 index 000000000..cd83e408d --- /dev/null +++ b/src/Microsoft.ComponentDetection.Detectors/pnpm/ParsingUtilities/PnpmV6ParsingUtilities.cs @@ -0,0 +1,42 @@ +namespace Microsoft.ComponentDetection.Detectors.Pnpm; + +using System; +using Microsoft.ComponentDetection.Contracts; +using Microsoft.ComponentDetection.Contracts.TypedComponent; + +public class PnpmV6ParsingUtilities : PnpmParsingUtilitiesBase +where T : PnpmYaml +{ + public override DetectedComponent CreateDetectedComponentFromPnpmPath(string pnpmPackagePath) + { + /* + * The format is documented at https://github.com/pnpm/spec/blob/master/dependency-path.md. + * At the writing it does not seem to reflect changes which were made in lock file format v6: + * See https://github.com/pnpm/spec/issues/5. + */ + + // Strip parenthesized suffices from package. These hold peed dep related information that is unneeded here. + // An example of a dependency path with these: /webpack-cli@4.10.0(webpack-bundle-analyzer@4.10.1)(webpack-dev-server@4.6.0)(webpack@5.89.0) + var fullPackageNameAndVersion = pnpmPackagePath.Split("(")[0]; + + var packageNameParts = fullPackageNameAndVersion.Split("@"); + + // If package name contains `@` this will reconstruct it: + var fullPackageName = string.Join("@", packageNameParts[..^1]); + + // Version is section after last `@`. + var packageVersion = packageNameParts[^1]; + + // Check for leading `/` from pnpm. + if (!fullPackageName.StartsWith('/')) + { + throw new FormatException("Found pnpm dependency path not starting with `/`. This case is currently unhandled."); + } + + // Strip leading `/`. + // It is unclear if real packages could have a name starting with `/`, so avoid `TrimStart` that just in case. + var normalizedPackageName = fullPackageName[1..]; + + return new DetectedComponent(new NpmComponent(normalizedPackageName, packageVersion)); + } +} diff --git a/src/Microsoft.ComponentDetection.Detectors/pnpm/ParsingUtilities/PnpmV9ParsingUtilities.cs b/src/Microsoft.ComponentDetection.Detectors/pnpm/ParsingUtilities/PnpmV9ParsingUtilities.cs new file mode 100644 index 000000000..3270fdc0e --- /dev/null +++ b/src/Microsoft.ComponentDetection.Detectors/pnpm/ParsingUtilities/PnpmV9ParsingUtilities.cs @@ -0,0 +1,54 @@ +namespace Microsoft.ComponentDetection.Detectors.Pnpm; + +using Microsoft.ComponentDetection.Contracts; +using Microsoft.ComponentDetection.Contracts.TypedComponent; + +public class PnpmV9ParsingUtilities : PnpmParsingUtilitiesBase +where T : PnpmYaml +{ + public override DetectedComponent CreateDetectedComponentFromPnpmPath(string pnpmPackagePath) + { + /* + * The format is documented at https://github.com/pnpm/spec/blob/master/dependency-path.md. + * At the writing it does not seem to reflect changes which were made in lock file format v9: + * See https://github.com/pnpm/spec/issues/5. + * In general, the spec sheet for the v9 lockfile is not published, so parsing of this lockfile was emperically determined. + * see https://github.com/pnpm/spec/issues/6 + */ + + // Strip parenthesized suffices from package. These hold peed dep related information that is unneeded here. + // An example of a dependency path with these: /webpack-cli@4.10.0(webpack-bundle-analyzer@4.10.1)(webpack-dev-server@4.6.0)(webpack@5.89.0) + var fullPackageNameAndVersion = pnpmPackagePath.Split("(")[0]; + + var packageNameParts = fullPackageNameAndVersion.Split("@"); + + // If package name contains `@` this will reconstruct it: + var fullPackageName = string.Join("@", packageNameParts[..^1]); + + // Version is section after last `@`. + var packageVersion = packageNameParts[^1]; + + return new DetectedComponent(new NpmComponent(fullPackageName, packageVersion)); + } + + /// + /// Combine the information from a dependency edge in the dependency graph encoded in the ymal file into a full pnpm dependency path. + /// + /// The name of the dependency, as used as as the dictionary key in the yaml file when referring to the dependency. + /// The final resolved version of the package for this dependency edge. + /// This includes details like which version of specific dependencies were specified as peer dependencies. + /// In some edge cases, such as aliased packages, this version may be an absolute dependency path, but the leading slash has been removed. + /// leaving the "dependencyName" unused, which is checked by whether there is an @ in the version. + /// A pnpm dependency path for the specified version of the named package. + public override string ReconstructPnpmDependencyPath(string dependencyName, string dependencyVersion) + { + if (dependencyVersion.StartsWith('/') || dependencyVersion.Split("(")[0].Contains('@')) + { + return dependencyVersion; + } + else + { + return $"{dependencyName}@{dependencyVersion}"; + } + } +} diff --git a/src/Microsoft.ComponentDetection.Detectors/pnpm/Pnpm5Detector.cs b/src/Microsoft.ComponentDetection.Detectors/pnpm/Pnpm5Detector.cs index b91403ffe..46273a00e 100644 --- a/src/Microsoft.ComponentDetection.Detectors/pnpm/Pnpm5Detector.cs +++ b/src/Microsoft.ComponentDetection.Detectors/pnpm/Pnpm5Detector.cs @@ -7,21 +7,22 @@ namespace Microsoft.ComponentDetection.Detectors.Pnpm; public class Pnpm5Detector : IPnpmDetector { public const string MajorVersion = "5"; + private readonly PnpmParsingUtilitiesBase pnpmParsingUtilities = PnpmParsingUtilitiesFactory.Create(); public void RecordDependencyGraphFromFile(string yamlFileContent, ISingleFileComponentRecorder singleFileComponentRecorder) { - var yaml = PnpmParsingUtilities.DeserializePnpmYamlV5File(yamlFileContent); + var yaml = this.pnpmParsingUtilities.DeserializePnpmYamlFile(yamlFileContent); - foreach (var packageKeyValue in yaml.Packages ?? Enumerable.Empty>()) + foreach (var packageKeyValue in yaml?.Packages ?? Enumerable.Empty>()) { // Ignore file: as these are local packages. - if (packageKeyValue.Key.StartsWith("file:")) + if (packageKeyValue.Key.StartsWith(PnpmConstants.PnpmFileDependencyPath)) { continue; } - var parentDetectedComponent = PnpmParsingUtilities.CreateDetectedComponentFromPnpmPathV5(pnpmPackagePath: packageKeyValue.Key); - var isDevDependency = packageKeyValue.Value != null && PnpmParsingUtilities.IsPnpmPackageDevDependency(packageKeyValue.Value); + var parentDetectedComponent = this.pnpmParsingUtilities.CreateDetectedComponentFromPnpmPath(pnpmPackagePath: packageKeyValue.Key); + var isDevDependency = packageKeyValue.Value != null && this.pnpmParsingUtilities.IsPnpmPackageDevDependency(packageKeyValue.Value); singleFileComponentRecorder.RegisterUsage(parentDetectedComponent, isDevelopmentDependency: isDevDependency); parentDetectedComponent = singleFileComponentRecorder.GetComponent(parentDetectedComponent.Component.Id); @@ -30,13 +31,13 @@ public void RecordDependencyGraphFromFile(string yamlFileContent, ISingleFileCom foreach (var dependency in packageKeyValue.Value.Dependencies) { // Ignore local packages. - if (PnpmParsingUtilities.IsLocalDependency(dependency)) + if (this.pnpmParsingUtilities.IsLocalDependency(dependency)) { continue; } - var childDetectedComponent = PnpmParsingUtilities.CreateDetectedComponentFromPnpmPathV5( - pnpmPackagePath: PnpmParsingUtilities.CreatePnpmPackagePathFromDependencyV5(dependency.Key, dependency.Value)); + var childDetectedComponent = this.pnpmParsingUtilities.CreateDetectedComponentFromPnpmPath( + pnpmPackagePath: this.CreatePnpmPackagePathFromDependency(dependency.Key, dependency.Value)); // Older code used the root's dev dependency value. We're leaving this null until we do a second pass to look at each components' top level referrers. singleFileComponentRecorder.RegisterUsage(childDetectedComponent, parentComponentId: parentDetectedComponent.Component.Id, isDevelopmentDependency: null); @@ -55,4 +56,9 @@ public void RecordDependencyGraphFromFile(string yamlFileContent, ISingleFileCom } } } + + private string CreatePnpmPackagePathFromDependency(string dependencyName, string dependencyVersion) + { + return dependencyVersion.Contains('/') ? dependencyVersion : $"/{dependencyName}/{dependencyVersion}"; + } } diff --git a/src/Microsoft.ComponentDetection.Detectors/pnpm/Pnpm6Detector.cs b/src/Microsoft.ComponentDetection.Detectors/pnpm/Pnpm6Detector.cs index 0a3e5a99e..98513fc6a 100644 --- a/src/Microsoft.ComponentDetection.Detectors/pnpm/Pnpm6Detector.cs +++ b/src/Microsoft.ComponentDetection.Detectors/pnpm/Pnpm6Detector.cs @@ -7,10 +7,11 @@ namespace Microsoft.ComponentDetection.Detectors.Pnpm; public class Pnpm6Detector : IPnpmDetector { public const string MajorVersion = "6"; + private readonly PnpmParsingUtilitiesBase pnpmParsingUtilities = PnpmParsingUtilitiesFactory.Create(); public void RecordDependencyGraphFromFile(string yamlFileContent, ISingleFileComponentRecorder singleFileComponentRecorder) { - var yaml = PnpmParsingUtilities.DeserializePnpmYamlV6File(yamlFileContent); + var yaml = this.pnpmParsingUtilities.DeserializePnpmYamlFile(yamlFileContent); // There may be multiple instance of the same package (even at the same version) in pnpm differentiated by other aspects of the pnpm dependency path. // Therefor all DetectedComponents are tracked by the same full string pnpm uses, the pnpm dependency path, which is used as the key in this dictionary. @@ -24,19 +25,19 @@ public void RecordDependencyGraphFromFile(string yamlFileContent, ISingleFileCom // Ignore "file:" as these are local packages. // Such local packages should only be referenced at the top level (via ProcessDependencyList) which also skips them or from other local packages (which this skips). // There should be no cases where a non-local package references a local package, so skipping them here should not result in failed lookups below when adding all the graph references. - if (pnpmDependencyPath.StartsWith("file:")) + if (pnpmDependencyPath.StartsWith(PnpmConstants.PnpmFileDependencyPath)) { continue; } - var parentDetectedComponent = PnpmParsingUtilities.CreateDetectedComponentFromPnpmPathV6(pnpmDependencyPath: pnpmDependencyPath); + var parentDetectedComponent = this.pnpmParsingUtilities.CreateDetectedComponentFromPnpmPath(pnpmPackagePath: pnpmDependencyPath); components.Add(pnpmDependencyPath, (parentDetectedComponent, package)); // Register the component. // It should get registered again with with additional information (what depended on it) later, // but registering it now ensures nothing is missed due to a limitation in dependency traversal // like skipping local dependencies which might have transitively depended on this. - singleFileComponentRecorder.RegisterUsage(parentDetectedComponent, isDevelopmentDependency: PnpmParsingUtilities.IsPnpmPackageDevDependency(package)); + singleFileComponentRecorder.RegisterUsage(parentDetectedComponent, isDevelopmentDependency: this.pnpmParsingUtilities.IsPnpmPackageDevDependency(package)); } // Now that the `components` dictionary is populated, make a second pass registering all the dependency edges in the graph. @@ -44,7 +45,7 @@ public void RecordDependencyGraphFromFile(string yamlFileContent, ISingleFileCom { foreach (var (name, version) in package.Dependencies ?? Enumerable.Empty>()) { - var pnpmDependencyPath = PnpmParsingUtilities.ReconstructPnpmDependencyPathV6(name, version); + var pnpmDependencyPath = this.pnpmParsingUtilities.ReconstructPnpmDependencyPath(name, version); // If this lookup fails, then pnpmDependencyPath was either parsed incorrectly or constructed incorrectly. var (referenced, _) = components[pnpmDependencyPath]; @@ -77,17 +78,17 @@ private void ProcessDependencyList(ISingleFileComponentRecorder singleFileCompon foreach (var (name, dep) in dependencies ?? Enumerable.Empty>()) { // Ignore "file:" and "link:" as these are local packages. - if (dep.Version.StartsWith("link:") || dep.Version.StartsWith("file:")) + if (dep.Version.StartsWith(PnpmConstants.PnpmLinkDependencyPath) || dep.Version.StartsWith(PnpmConstants.PnpmFileDependencyPath)) { continue; } - var pnpmDependencyPath = PnpmParsingUtilities.ReconstructPnpmDependencyPathV6(name, dep.Version); + var pnpmDependencyPath = this.pnpmParsingUtilities.ReconstructPnpmDependencyPath(name, dep.Version); var (component, package) = components[pnpmDependencyPath]; // Determine isDevelopmentDependency using metadata on package from pnpm rather than from which dependency list this package is under. // This ensures that dependencies which are a direct dev dependency and an indirect non-dev dependency get listed as non-dev. - var isDevelopmentDependency = PnpmParsingUtilities.IsPnpmPackageDevDependency(package); + var isDevelopmentDependency = this.pnpmParsingUtilities.IsPnpmPackageDevDependency(package); singleFileComponentRecorder.RegisterUsage(component, isExplicitReferencedDependency: true, isDevelopmentDependency: isDevelopmentDependency); } diff --git a/src/Microsoft.ComponentDetection.Detectors/pnpm/Pnpm9Detector.cs b/src/Microsoft.ComponentDetection.Detectors/pnpm/Pnpm9Detector.cs new file mode 100644 index 000000000..82e1093a8 --- /dev/null +++ b/src/Microsoft.ComponentDetection.Detectors/pnpm/Pnpm9Detector.cs @@ -0,0 +1,114 @@ +namespace Microsoft.ComponentDetection.Detectors.Pnpm; + +using System.Collections.Generic; +using System.Linq; +using Microsoft.ComponentDetection.Contracts; + +/// +/// There is still no official docs for the new v9 lock format, so these parsing contracts are empirically based. +/// Issue tracking v9 specs: https://github.com/pnpm/spec/issues/6 +/// Format should eventually get updated here: https://github.com/pnpm/spec/blob/master/lockfile/6.0.md. +/// +public class Pnpm9Detector : IPnpmDetector +{ + public const string MajorVersion = "9"; + private readonly PnpmParsingUtilitiesBase pnpmParsingUtilities = PnpmParsingUtilitiesFactory.Create(); + + public void RecordDependencyGraphFromFile(string yamlFileContent, ISingleFileComponentRecorder singleFileComponentRecorder) + { + var yaml = this.pnpmParsingUtilities.DeserializePnpmYamlFile(yamlFileContent); + + // There may be multiple instance of the same package (even at the same version) in pnpm differentiated by other aspects of the pnpm dependency path. + // Therefor all DetectedComponents are tracked by the same full string pnpm uses, the pnpm dependency path, which is used as the key in this dictionary. + // Some documentation about pnpm dependency paths can be found at https://github.com/pnpm/spec/blob/master/dependency-path.md. + var components = new Dictionary(); + + // Create a component for every package referenced in the lock file. + // This includes all directly and transitively referenced dependencies. + foreach (var (pnpmDependencyPath, package) in yaml.Snapshots ?? Enumerable.Empty>()) + { + // Ignore "file:" as these are local packages. + // Such local packages should only be referenced at the top level (via ProcessDependencyList) which also skips them or from other local packages (which this skips). + // There should be no cases where a non-local package references a local package, so skipping them here should not result in failed lookups below when adding all the graph references. + if (pnpmDependencyPath.StartsWith(PnpmConstants.PnpmFileDependencyPath)) + { + continue; + } + + var dependencyPath = pnpmDependencyPath; + if (pnpmDependencyPath.StartsWith('/')) + { + dependencyPath = pnpmDependencyPath[1..]; + } + + var parentDetectedComponent = this.pnpmParsingUtilities.CreateDetectedComponentFromPnpmPath(pnpmPackagePath: dependencyPath); + components.Add(dependencyPath, (parentDetectedComponent, package)); + + // Register the component. + // It should get registered again with with additional information (what depended on it) later, + // but registering it now ensures nothing is missed due to a limitation in dependency traversal + // like skipping local dependencies which might have transitively depended on this. + singleFileComponentRecorder.RegisterUsage(parentDetectedComponent); + } + + // now that the components dictionary is populated, add direct dependencies of the current file/project setting isExplicitReferencedDependency to true + // during this step, recursively processes any indirect dependencies + foreach (var (_, package) in yaml.Importers ?? Enumerable.Empty>()) + { + this.ProcessDependencySets(singleFileComponentRecorder, components, package); + } + } + + private void ProcessDependencySets(ISingleFileComponentRecorder singleFileComponentRecorder, Dictionary components, PnpmHasDependenciesV9 item) + { + this.ProcessDependencyList(singleFileComponentRecorder, components, item.Dependencies, isDevelopmentDependency: false); + this.ProcessDependencyList(singleFileComponentRecorder, components, item.DevDependencies, isDevelopmentDependency: true); + this.ProcessDependencyList(singleFileComponentRecorder, components, item.OptionalDependencies, false); + } + + private void ProcessDependencyList(ISingleFileComponentRecorder singleFileComponentRecorder, Dictionary components, Dictionary dependencies, bool isDevelopmentDependency) + { + foreach (var (name, dep) in dependencies ?? Enumerable.Empty>()) + { + // Ignore "file:" and "link:" as these are local packages. + if (dep.Version.StartsWith(PnpmConstants.PnpmLinkDependencyPath) || dep.Version.StartsWith(PnpmConstants.PnpmFileDependencyPath)) + { + continue; + } + + var pnpmDependencyPath = this.pnpmParsingUtilities.ReconstructPnpmDependencyPath(name, dep.Version); + var (component, package) = components[pnpmDependencyPath]; + + // Lockfile v9 apparently removed the tagging of dev dependencies in the lockfile, so we revert to using the dependency tree to establish dev dependency state. + // At this point, the root dependencies are marked according to which dependency group they are declared in the lockfile itself. + singleFileComponentRecorder.RegisterUsage(component, isExplicitReferencedDependency: true, isDevelopmentDependency: isDevelopmentDependency); + var seenDependencies = new HashSet(); + this.ProcessIndirectDependencies(singleFileComponentRecorder, components, component.Component.Id, package.Dependencies, isDevelopmentDependency, seenDependencies); + } + } + + private void ProcessIndirectDependencies(ISingleFileComponentRecorder singleFileComponentRecorder, Dictionary components, string parentComponentId, Dictionary dependencies, bool isDevDependency, HashSet seenDependencies) + { + // Now that the `components` dictionary is populated, make another pass of all components, registering all the dependency edges in the graph. + foreach (var (name, version) in dependencies ?? Enumerable.Empty>()) + { + // Ignore "file:" and "link:" as these are local packages. + if (version.StartsWith(PnpmConstants.PnpmLinkDependencyPath) || version.StartsWith(PnpmConstants.PnpmFileDependencyPath)) + { + continue; + } + + var pnpmDependencyPath = this.pnpmParsingUtilities.ReconstructPnpmDependencyPath(name, version); + if (seenDependencies.Contains(pnpmDependencyPath)) + { + continue; + } + + // If this lookup fails, then pnpmDependencyPath was either parsed incorrectly or constructed incorrectly. + var (component, package) = components[pnpmDependencyPath]; + singleFileComponentRecorder.RegisterUsage(component, parentComponentId: parentComponentId, isExplicitReferencedDependency: false, isDevelopmentDependency: isDevDependency); + seenDependencies.Add(pnpmDependencyPath); + this.ProcessIndirectDependencies(singleFileComponentRecorder, components, component.Component.Id, package.Dependencies, isDevDependency, seenDependencies); + } + } +} diff --git a/src/Microsoft.ComponentDetection.Detectors/pnpm/PnpmComponentDetectorFactory.cs b/src/Microsoft.ComponentDetection.Detectors/pnpm/PnpmComponentDetectorFactory.cs index a4cd8824b..2bc3e7880 100644 --- a/src/Microsoft.ComponentDetection.Detectors/pnpm/PnpmComponentDetectorFactory.cs +++ b/src/Microsoft.ComponentDetection.Detectors/pnpm/PnpmComponentDetectorFactory.cs @@ -21,7 +21,7 @@ public class PnpmComponentDetectorFactory : FileComponentDetector /// /// The maximum version of the report specification that this detector can handle. /// - private static readonly Version MaxLockfileVersion = new(6, 0); + private static readonly Version MaxLockfileVersion = new(9, 0); public PnpmComponentDetectorFactory( IComponentStreamEnumerableFactory componentStreamEnumerableFactory, @@ -41,7 +41,7 @@ public PnpmComponentDetectorFactory( public override IEnumerable SupportedComponentTypes { get; } = [ComponentType.Npm]; - public override int Version { get; } = 6; + public override int Version { get; } = 7; public override bool NeedsAutomaticRootDependencyCalculation => true; @@ -98,7 +98,7 @@ protected override async Task OnFileFoundAsync(ProcessRequest processRequest, ID private IPnpmDetector GetPnpmComponentDetector(string fileContent, out string detectedVersion) { - detectedVersion = PnpmParsingUtilities.DeserializePnpmYamlFileVersion(fileContent); + detectedVersion = PnpmParsingUtilitiesFactory.DeserializePnpmYamlFileVersion(fileContent); this.RecordLockfileVersion(detectedVersion); var majorVersion = detectedVersion?.Split(".")[0]; return majorVersion switch @@ -110,6 +110,7 @@ private IPnpmDetector GetPnpmComponentDetector(string fileContent, out string de null => new Pnpm5Detector(), Pnpm5Detector.MajorVersion => new Pnpm5Detector(), Pnpm6Detector.MajorVersion => new Pnpm6Detector(), + Pnpm9Detector.MajorVersion => new Pnpm9Detector(), _ => null, }; } diff --git a/src/Microsoft.ComponentDetection.Detectors/pnpm/PnpmParsingUtilities.cs b/src/Microsoft.ComponentDetection.Detectors/pnpm/PnpmParsingUtilities.cs deleted file mode 100644 index fe107d9ec..000000000 --- a/src/Microsoft.ComponentDetection.Detectors/pnpm/PnpmParsingUtilities.cs +++ /dev/null @@ -1,167 +0,0 @@ -namespace Microsoft.ComponentDetection.Detectors.Pnpm; - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using global::NuGet.Versioning; -using Microsoft.ComponentDetection.Contracts; -using Microsoft.ComponentDetection.Contracts.TypedComponent; -using YamlDotNet.Serialization; - -public static class PnpmParsingUtilities -{ - public static string DeserializePnpmYamlFileVersion(string fileContent) - { - var deserializer = new DeserializerBuilder() - .IgnoreUnmatchedProperties() - .Build(); - return deserializer.Deserialize(new StringReader(fileContent)).LockfileVersion; - } - - public static bool IsPnpmPackageDevDependency(Package pnpmPackage) - { - ArgumentNullException.ThrowIfNull(pnpmPackage); - - return string.Equals(bool.TrueString, pnpmPackage.Dev, StringComparison.InvariantCultureIgnoreCase); - } - - public static PnpmYamlV5 DeserializePnpmYamlV5File(string fileContent) - { - var deserializer = new DeserializerBuilder() - .IgnoreUnmatchedProperties() - .Build(); - return deserializer.Deserialize(new StringReader(fileContent)); - } - - public static PnpmYamlV6 DeserializePnpmYamlV6File(string fileContent) - { - var deserializer = new DeserializerBuilder() - .IgnoreUnmatchedProperties() - .Build(); - return deserializer.Deserialize(new StringReader(fileContent)); - } - - public static bool IsLocalDependency(KeyValuePair dependency) - { - // Local dependencies are dependencies that live in the file system - // this requires an extra parsing that is not supported yet - return dependency.Key.StartsWith("file:") || dependency.Value.StartsWith("file:") || dependency.Value.StartsWith("link:"); - } - - /// - /// Parse a pnpm path of the form "/package-name/version". - /// - /// a pnpm path of the form "/package-name/version". - /// Data parsed from path. - public static DetectedComponent CreateDetectedComponentFromPnpmPathV5(string pnpmPackagePath) - { - var (parentName, parentVersion) = ExtractNameAndVersionFromPnpmPackagePathV5(pnpmPackagePath); - return new DetectedComponent(new NpmComponent(parentName, parentVersion)); - } - - public static string CreatePnpmPackagePathFromDependencyV5(string dependencyName, string dependencyVersion) - { - return dependencyVersion.Contains('/') ? dependencyVersion : $"/{dependencyName}/{dependencyVersion}"; - } - - private static (string Name, string Version) ExtractNameAndVersionFromPnpmPackagePathV5(string pnpmPackagePath) - { - var pnpmComponentDefSections = pnpmPackagePath.Trim('/').Split('/'); - (var packageVersion, var indexVersionIsAt) = GetPackageVersionV5(pnpmComponentDefSections); - if (indexVersionIsAt == -1) - { - // No version = not expected input - return (null, null); - } - - var normalizedPackageName = string.Join("/", pnpmComponentDefSections.Take(indexVersionIsAt).ToArray()); - return (normalizedPackageName, packageVersion); - } - - private static (string PackageVersion, int VersionIndex) GetPackageVersionV5(string[] pnpmComponentDefSections) - { - var indexVersionIsAt = -1; - var packageVersion = string.Empty; - var lastIndex = pnpmComponentDefSections.Length - 1; - - // get version from packages with format /mute-stream/0.0.6 - if (SemanticVersion.TryParse(pnpmComponentDefSections[lastIndex], out var _)) - { - return (pnpmComponentDefSections[lastIndex], lastIndex); - } - - // get version from packages with format /@babel/helper-compilation-targets/7.10.4_@babel+core@7.10.5 - var lastComponentSplit = pnpmComponentDefSections[lastIndex].Split("_"); - if (SemanticVersion.TryParse(lastComponentSplit[0], out var _)) - { - return (lastComponentSplit[0], lastIndex); - } - - // get version from packages with format /sinon-chai/2.8.0/chai@3.5.0+sinon@1.17.7 - if (SemanticVersion.TryParse(pnpmComponentDefSections[lastIndex - 1], out var _)) - { - return (pnpmComponentDefSections[lastIndex - 1], lastIndex - 1); - } - - return (packageVersion, indexVersionIsAt); - } - - /// - /// Parse a pnpm dependency path. - /// - /// A pnpm dependency path of the form "/@optional-scope/package-name@version(optional-ignored-data)(optional-ignored-data)". - /// Data parsed from path. - public static DetectedComponent CreateDetectedComponentFromPnpmPathV6(string pnpmDependencyPath) - { - /* - * The format is documented at https://github.com/pnpm/spec/blob/master/dependency-path.md. - * At the writing it does not seem to reflect changes which were made in lock file format v6: - * See https://github.com/pnpm/spec/issues/5. - */ - - // Strip parenthesized suffices from package. These hold peed dep related information that is unneeded here. - // An example of a dependency path with these: /webpack-cli@4.10.0(webpack-bundle-analyzer@4.10.1)(webpack-dev-server@4.6.0)(webpack@5.89.0) - var fullPackageNameAndVersion = pnpmDependencyPath.Split("(")[0]; - - var packageNameParts = fullPackageNameAndVersion.Split("@"); - - // If package name contains `@` this will reconstruct it: - var fullPackageName = string.Join("@", packageNameParts[..^1]); - - // Version is section after last `@`. - var packageVersion = packageNameParts[^1]; - - // Check for leading `/` from pnpm. - if (!fullPackageName.StartsWith('/')) - { - throw new FormatException("Found pnpm dependency path not starting with `/`. This case is currently unhandled."); - } - - // Strip leading `/`. - // It is unclear if real packages could have a name starting with `/`, so avoid `TrimStart` that just in case. - var normalizedPackageName = fullPackageName[1..]; - - return new DetectedComponent(new NpmComponent(normalizedPackageName, packageVersion)); - } - - /// - /// Combine the information from a dependency edge in the dependency graph encoded in the ymal file into a full pnpm dependency path. - /// - /// The name of the dependency, as used as as the dictionary key in the yaml file when referring to the dependency. - /// The final resolved version of the package for this dependency edge. - /// This includes details like which version of specific dependencies were specified as peer dependencies. - /// In some edge cases, such as aliased packages, this version may be an absolute dependency path (starts with a slash) leaving the "dependencyName" unused. - /// A pnpm dependency path for the specified version of the named package. - public static string ReconstructPnpmDependencyPathV6(string dependencyName, string dependencyVersion) - { - if (dependencyVersion.StartsWith('/')) - { - return dependencyVersion; - } - else - { - return $"/{dependencyName}@{dependencyVersion}"; - } - } -} diff --git a/test/Microsoft.ComponentDetection.Detectors.Tests/PnpmDetectorTests.cs b/test/Microsoft.ComponentDetection.Detectors.Tests/PnpmDetectorTests.cs index 6f94f34aa..e4c60c077 100644 --- a/test/Microsoft.ComponentDetection.Detectors.Tests/PnpmDetectorTests.cs +++ b/test/Microsoft.ComponentDetection.Detectors.Tests/PnpmDetectorTests.cs @@ -332,10 +332,12 @@ public async Task TestPnpmDetector_DependencyGraphIsCreatedAsync() scanResult.ResultCode.Should().Be(ProcessingResultCode.Success); componentRecorder.GetDetectedComponents().Should().HaveCount(4); - var queryStringComponentId = PnpmParsingUtilities.CreateDetectedComponentFromPnpmPathV5("/query-string/4.3.4").Component.Id; - var objectAssignComponentId = PnpmParsingUtilities.CreateDetectedComponentFromPnpmPathV5("/object-assign/4.1.1").Component.Id; - var strictUriComponentId = PnpmParsingUtilities.CreateDetectedComponentFromPnpmPathV5("/strict-uri-encode/1.1.0").Component.Id; - var testComponentId = PnpmParsingUtilities.CreateDetectedComponentFromPnpmPathV5("/test/1.0.0").Component.Id; + var pnpmParsingUtilities = PnpmParsingUtilitiesFactory.Create(); + + var queryStringComponentId = pnpmParsingUtilities.CreateDetectedComponentFromPnpmPath("/query-string/4.3.4").Component.Id; + var objectAssignComponentId = pnpmParsingUtilities.CreateDetectedComponentFromPnpmPath("/object-assign/4.1.1").Component.Id; + var strictUriComponentId = pnpmParsingUtilities.CreateDetectedComponentFromPnpmPath("/strict-uri-encode/1.1.0").Component.Id; + var testComponentId = pnpmParsingUtilities.CreateDetectedComponentFromPnpmPath("/test/1.0.0").Component.Id; var dependencyGraph = componentRecorder.GetDependencyGraphsByLocation().Values.First(); @@ -380,8 +382,10 @@ public async Task TestPnpmDetector_DependenciesRefeToLocalPaths_DependenciesAreI scanResult.ResultCode.Should().Be(ProcessingResultCode.Success); componentRecorder.GetDetectedComponents().Should().HaveCount(2, "Components that comes from a file (file:* or link:*) should be ignored."); - var queryStringComponentId = PnpmParsingUtilities.CreateDetectedComponentFromPnpmPathV5("/query-string/4.3.4").Component.Id; - var nthcheck = PnpmParsingUtilities.CreateDetectedComponentFromPnpmPathV5("/nth-check/2.0.0").Component.Id; + var pnpmParsingUtilities = PnpmParsingUtilitiesFactory.Create(); + + var queryStringComponentId = pnpmParsingUtilities.CreateDetectedComponentFromPnpmPath("/query-string/4.3.4").Component.Id; + var nthcheck = pnpmParsingUtilities.CreateDetectedComponentFromPnpmPath("/nth-check/2.0.0").Component.Id; var dependencyGraph = componentRecorder.GetDependencyGraphsByLocation().Values.First(); @@ -600,4 +604,208 @@ public async Task TestPnpmDetector_V6_BadLockVersion_EmptyAsync() var detectedComponents = componentRecorder.GetDetectedComponents(); detectedComponents.Should().BeEmpty(); } + + [TestMethod] + public async Task TestPnpmDetector_V9_GoodLockVersion_ParsesDependencies() + { + var yamlFile = @" +lockfileVersion: '9.0' +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false +importers: + .: + dependencies: + sampleDependency: + specifier: ^1.1.1 + version: 1.1.1 + devDependencies: + sampleDevDependency: + specifier: ^2.2.2 + version: 2.2.2 +packages: + sampleDependency@1.1.1: + resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} + sampleDevDependency@2.2.2: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + sampleIndirectDependency@3.3.3: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + +snapshots: + sampleDependency@1.1.1: + dependencies: + sampleIndirectDependency: 3.3.3 + sampleDevDependency@2.2.2: {} + sampleIndirectDependency@3.3.3: {} +"; + + var (scanResult, componentRecorder) = await this.DetectorTestUtility + .WithFile("pnpm-lock.yaml", yamlFile) + .ExecuteDetectorAsync(); + + scanResult.ResultCode.Should().Be(ProcessingResultCode.Success); + + var detectedComponents = componentRecorder.GetDetectedComponents(); + detectedComponents.Should().HaveCount(3); + var npmComponents = detectedComponents.Select(x => new { Component = x.Component as NpmComponent, DetectedComponent = x }); + npmComponents.Should().Contain(x => x.Component.Name == "sampleDependency" && x.Component.Version == "1.1.1"); + npmComponents.Should().Contain(x => x.Component.Name == "sampleDevDependency" && x.Component.Version == "2.2.2"); + npmComponents.Should().Contain(x => x.Component.Name == "sampleIndirectDependency" && x.Component.Version == "3.3.3"); + + var noDevDependencyComponent = npmComponents.First(x => x.Component.Name == "sampleDependency"); + var devDependencyComponent = npmComponents.First(x => x.Component.Name == "sampleDevDependency"); + var indirectDependencyComponent = npmComponents.First(x => x.Component.Name == "sampleIndirectDependency"); + + componentRecorder.GetEffectiveDevDependencyValue(noDevDependencyComponent.Component.Id).Should().BeFalse(); + componentRecorder.GetEffectiveDevDependencyValue(devDependencyComponent.Component.Id).Should().BeTrue(); + componentRecorder.AssertAllExplicitlyReferencedComponents( + indirectDependencyComponent.Component.Id, + parentComponent => parentComponent.Name == "sampleDependency"); + } + + [TestMethod] + public async Task TestPnpmDetector_V9_GoodLockVersion_ParsesAliasedDependency() + { + var yamlFile = @" +lockfileVersion: '9.0' +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false +importers: + .: + dependencies: + aliasedSample: + specifier: npm:sampleDependency@1.1.1 + version: sampleDependency@1.1.1 +packages: + sampleDependency@1.1.1: + resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} + sampleIndirectDependency@3.3.3: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + +snapshots: + sampleDependency@1.1.1: + dependencies: + sampleIndirectDependency: 3.3.3 + sampleIndirectDependency@3.3.3: {} +"; + + var (scanResult, componentRecorder) = await this.DetectorTestUtility + .WithFile("pnpm-lock.yaml", yamlFile) + .ExecuteDetectorAsync(); + + scanResult.ResultCode.Should().Be(ProcessingResultCode.Success); + + var detectedComponents = componentRecorder.GetDetectedComponents(); + detectedComponents.Should().HaveCount(2); + var npmComponents = detectedComponents.Select(x => new { Component = x.Component as NpmComponent, DetectedComponent = x }); + npmComponents.Should().Contain(x => x.Component.Name == "sampleDependency" && x.Component.Version == "1.1.1"); + npmComponents.Should().Contain(x => x.Component.Name == "sampleIndirectDependency" && x.Component.Version == "3.3.3"); + + var noDevDependencyComponent = npmComponents.First(x => x.Component.Name == "sampleDependency"); + var indirectDependencyComponent = npmComponents.First(x => x.Component.Name == "sampleIndirectDependency"); + + componentRecorder.GetEffectiveDevDependencyValue(noDevDependencyComponent.Component.Id).Should().BeFalse(); + componentRecorder.AssertAllExplicitlyReferencedComponents( + indirectDependencyComponent.Component.Id, + parentComponent => parentComponent.Name == "sampleDependency"); + } + + [TestMethod] + public async Task TestPnpmDetector_V9_GoodLockVersion_SkipsFileAndLinkDependencies() + { + var yamlFile = @" +lockfileVersion: '9.0' +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false +importers: + .: + dependencies: + sampleDependency: + specifier: ^1.1.1 + version: 1.1.1 + SampleFileDependency: + specifier: file://../sampleFile + version: link:../ + SampleLinkDependency: + specifier: workspace:* + version: link:SampleLinkDependency +packages: + sampleDependency@1.1.1: + resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} + sampleIndirectDependency2@2.2.2: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + sampleIndirectDependency@3.3.3: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + +snapshots: + sampleDependency@1.1.1: + dependencies: + sampleIndirectDependency: 3.3.3 + sampleIndirectDependency2: 2.2.2 + 'file://../sampleFile': 'link:../\\' + sampleIndirectDependency2@2.2.2: {} + sampleIndirectDependency@3.3.3: {} + 'file://../sampleFile@link:../': {} +"; + + var (scanResult, componentRecorder) = await this.DetectorTestUtility + .WithFile("pnpm-lock.yaml", yamlFile) + .ExecuteDetectorAsync(); + + scanResult.ResultCode.Should().Be(ProcessingResultCode.Success); + + var detectedComponents = componentRecorder.GetDetectedComponents(); + detectedComponents.Should().HaveCount(3); + var npmComponents = detectedComponents.Select(x => new { Component = x.Component as NpmComponent, DetectedComponent = x }); + npmComponents.Should().Contain(x => x.Component.Name == "sampleDependency" && x.Component.Version == "1.1.1"); + npmComponents.Should().Contain(x => x.Component.Name == "sampleIndirectDependency2" && x.Component.Version == "2.2.2"); + npmComponents.Should().Contain(x => x.Component.Name == "sampleIndirectDependency" && x.Component.Version == "3.3.3"); + + var noDevDependencyComponent = npmComponents.First(x => x.Component.Name == "sampleDependency"); + var indirectDependencyComponent2 = npmComponents.First(x => x.Component.Name == "sampleIndirectDependency2"); + var indirectDependencyComponent = npmComponents.First(x => x.Component.Name == "sampleIndirectDependency"); + + componentRecorder.GetEffectiveDevDependencyValue(noDevDependencyComponent.Component.Id).Should().BeFalse(); + componentRecorder.GetEffectiveDevDependencyValue(indirectDependencyComponent2.Component.Id).Should().BeFalse(); + componentRecorder.GetEffectiveDevDependencyValue(indirectDependencyComponent.Component.Id).Should().BeFalse(); + componentRecorder.AssertAllExplicitlyReferencedComponents( + indirectDependencyComponent.Component.Id, + parentComponent => parentComponent.Name == "sampleDependency"); + componentRecorder.AssertAllExplicitlyReferencedComponents( + indirectDependencyComponent2.Component.Id, + parentComponent => parentComponent.Name == "sampleDependency"); + } + + [TestMethod] + public async Task TestPnpmDetector_V9_GoodLockVersion_MissingSnapshotsSuccess() + { + var yamlFile = @" +lockfileVersion: '9.0' +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false +importers: + .: + dependencies: + SampleLinkDependency: + specifier: workspace:* + version: link:SampleLinkDependency +"; + + var (scanResult, componentRecorder) = await this.DetectorTestUtility + .WithFile("pnpm-lock.yaml", yamlFile) + .ExecuteDetectorAsync(); + + scanResult.ResultCode.Should().Be(ProcessingResultCode.Success); + + var detectedComponents = componentRecorder.GetDetectedComponents(); + detectedComponents.Should().BeEmpty(); + } } diff --git a/test/Microsoft.ComponentDetection.Detectors.Tests/PnpmParsingUtilitiesTest.cs b/test/Microsoft.ComponentDetection.Detectors.Tests/PnpmParsingUtilitiesTest.cs index ba508d5a5..6f87db271 100644 --- a/test/Microsoft.ComponentDetection.Detectors.Tests/PnpmParsingUtilitiesTest.cs +++ b/test/Microsoft.ComponentDetection.Detectors.Tests/PnpmParsingUtilitiesTest.cs @@ -35,10 +35,10 @@ public void DeserializePnpmYamlFileV3() registry: 'https://test/registry' shrinkwrapMinorVersion: 7 shrinkwrapVersion: 3"; - - var version = PnpmParsingUtilities.DeserializePnpmYamlFileVersion(yamlFile); + var pnpmParsingUtilities = PnpmParsingUtilitiesFactory.Create(); + var version = PnpmParsingUtilitiesFactory.DeserializePnpmYamlFileVersion(yamlFile); version.Should().BeNull(); // Versions older than 5 report null as they don't use the same version field. - var parsedYaml = PnpmParsingUtilities.DeserializePnpmYamlV5File(yamlFile); + var parsedYaml = pnpmParsingUtilities.DeserializePnpmYamlFile(yamlFile); parsedYaml.Packages.Should().HaveCount(2); parsedYaml.Packages.Should().ContainKey("/query-string/4.3.4"); @@ -58,19 +58,20 @@ public void DeserializePnpmYamlFileV3() [TestMethod] public void CreateDetectedComponentFromPnpmPathV5() { - var detectedComponent1 = PnpmParsingUtilities.CreateDetectedComponentFromPnpmPathV5("/@ms/items-view/0.128.9/react-dom@15.6.2+react@15.6.2"); + var pnpmParsingUtilities = PnpmParsingUtilitiesFactory.Create(); + var detectedComponent1 = pnpmParsingUtilities.CreateDetectedComponentFromPnpmPath("/@ms/items-view/0.128.9/react-dom@15.6.2+react@15.6.2"); detectedComponent1.Should().NotBeNull(); detectedComponent1.Component.Should().NotBeNull(); ((NpmComponent)detectedComponent1.Component).Name.Should().BeEquivalentTo("@ms/items-view"); ((NpmComponent)detectedComponent1.Component).Version.Should().BeEquivalentTo("0.128.9"); - var detectedComponent2 = PnpmParsingUtilities.CreateDetectedComponentFromPnpmPathV5("/@babel/helper-compilation-targets/7.10.4_@babel+core@7.10.5"); + var detectedComponent2 = pnpmParsingUtilities.CreateDetectedComponentFromPnpmPath("/@babel/helper-compilation-targets/7.10.4_@babel+core@7.10.5"); detectedComponent2.Should().NotBeNull(); detectedComponent2.Component.Should().NotBeNull(); ((NpmComponent)detectedComponent2.Component).Name.Should().BeEquivalentTo("@babel/helper-compilation-targets"); ((NpmComponent)detectedComponent2.Component).Version.Should().BeEquivalentTo("7.10.4"); - var detectedComponent3 = PnpmParsingUtilities.CreateDetectedComponentFromPnpmPathV5("/query-string/4.3.4"); + var detectedComponent3 = pnpmParsingUtilities.CreateDetectedComponentFromPnpmPath("/query-string/4.3.4"); detectedComponent3.Should().NotBeNull(); detectedComponent3.Component.Should().NotBeNull(); ((NpmComponent)detectedComponent3.Component).Name.Should().BeEquivalentTo("query-string"); @@ -85,24 +86,26 @@ public void IsPnpmPackageDevDependency() Dev = "true", }; - PnpmParsingUtilities.IsPnpmPackageDevDependency(pnpmPackage).Should().BeTrue(); + var pnpmParsingUtilities = PnpmParsingUtilitiesFactory.Create(); + + pnpmParsingUtilities.IsPnpmPackageDevDependency(pnpmPackage).Should().BeTrue(); pnpmPackage.Dev = "TRUE"; - PnpmParsingUtilities.IsPnpmPackageDevDependency(pnpmPackage).Should().BeTrue(); + pnpmParsingUtilities.IsPnpmPackageDevDependency(pnpmPackage).Should().BeTrue(); pnpmPackage.Dev = "false"; - PnpmParsingUtilities.IsPnpmPackageDevDependency(pnpmPackage).Should().BeFalse(); + pnpmParsingUtilities.IsPnpmPackageDevDependency(pnpmPackage).Should().BeFalse(); pnpmPackage.Dev = "FALSE"; - PnpmParsingUtilities.IsPnpmPackageDevDependency(pnpmPackage).Should().BeFalse(); + pnpmParsingUtilities.IsPnpmPackageDevDependency(pnpmPackage).Should().BeFalse(); pnpmPackage.Dev = string.Empty; - PnpmParsingUtilities.IsPnpmPackageDevDependency(pnpmPackage).Should().BeFalse(); + pnpmParsingUtilities.IsPnpmPackageDevDependency(pnpmPackage).Should().BeFalse(); pnpmPackage.Dev = null; - PnpmParsingUtilities.IsPnpmPackageDevDependency(pnpmPackage).Should().BeFalse(); + pnpmParsingUtilities.IsPnpmPackageDevDependency(pnpmPackage).Should().BeFalse(); - Action action = () => PnpmParsingUtilities.IsPnpmPackageDevDependency(null); + Action action = () => pnpmParsingUtilities.IsPnpmPackageDevDependency(null); action.Should().Throw(); } @@ -123,10 +126,10 @@ public void DeserializePnpmYamlFileV6() /minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} dev: false"; - - var version = PnpmParsingUtilities.DeserializePnpmYamlFileVersion(yamlFile); + var pnpmParsingUtilities = PnpmParsingUtilitiesFactory.Create(); + var version = PnpmParsingUtilitiesFactory.DeserializePnpmYamlFileVersion(yamlFile); version.Should().Be("6.0"); - var parsedYaml = PnpmParsingUtilities.DeserializePnpmYamlV6File(yamlFile); + var parsedYaml = pnpmParsingUtilities.DeserializePnpmYamlFile(yamlFile); parsedYaml.Packages.Should().ContainSingle(); parsedYaml.Packages.Should().ContainKey("/minimist@1.2.8"); @@ -142,23 +145,25 @@ public void DeserializePnpmYamlFileV6() [TestMethod] public void CreateDetectedComponentFromPnpmPathV6() { + var pnpmParsingUtilities = PnpmParsingUtilitiesFactory.Create(); + // Simple case: no scope, simple version - var simple = PnpmParsingUtilities.CreateDetectedComponentFromPnpmPathV6("/sort-scripts@1.0.1"); + var simple = pnpmParsingUtilities.CreateDetectedComponentFromPnpmPath("/sort-scripts@1.0.1"); ((NpmComponent)simple.Component).Name.Should().BeEquivalentTo("sort-scripts"); ((NpmComponent)simple.Component).Version.Should().BeEquivalentTo("1.0.1"); // With scope: - var scoped = PnpmParsingUtilities.CreateDetectedComponentFromPnpmPathV6("/@babel/eslint-parser@7.23.3"); + var scoped = pnpmParsingUtilities.CreateDetectedComponentFromPnpmPath("/@babel/eslint-parser@7.23.3"); ((NpmComponent)scoped.Component).Name.Should().BeEquivalentTo("@babel/eslint-parser"); ((NpmComponent)scoped.Component).Version.Should().BeEquivalentTo("7.23.3"); // With peer deps: - var withPeerDeps = PnpmParsingUtilities.CreateDetectedComponentFromPnpmPathV6("/mocha-json-output-reporter@2.1.0(mocha@10.2.0)(moment@2.29.4)"); + var withPeerDeps = pnpmParsingUtilities.CreateDetectedComponentFromPnpmPath("/mocha-json-output-reporter@2.1.0(mocha@10.2.0)(moment@2.29.4)"); ((NpmComponent)withPeerDeps.Component).Name.Should().BeEquivalentTo("mocha-json-output-reporter"); ((NpmComponent)withPeerDeps.Component).Version.Should().BeEquivalentTo("2.1.0"); // With everything: - var complex = PnpmParsingUtilities.CreateDetectedComponentFromPnpmPathV6("/@babel/eslint-parser@7.23.3(@babel/core@7.23.3)(eslint@8.55.0)"); + var complex = pnpmParsingUtilities.CreateDetectedComponentFromPnpmPath("/@babel/eslint-parser@7.23.3(@babel/core@7.23.3)(eslint@8.55.0)"); ((NpmComponent)complex.Component).Name.Should().BeEquivalentTo("@babel/eslint-parser"); ((NpmComponent)complex.Component).Version.Should().BeEquivalentTo("7.23.3"); } @@ -166,16 +171,18 @@ public void CreateDetectedComponentFromPnpmPathV6() [TestMethod] public void ReconstructPnpmDependencyPathV6() { + var pnpmParsingUtilities = PnpmParsingUtilitiesFactory.Create(); + // Simple case: no scope, simple version - PnpmParsingUtilities.ReconstructPnpmDependencyPathV6("sort-scripts", "1.0.1").Should().BeEquivalentTo("/sort-scripts@1.0.1"); + pnpmParsingUtilities.ReconstructPnpmDependencyPath("sort-scripts", "1.0.1").Should().BeEquivalentTo("/sort-scripts@1.0.1"); // With scope: - PnpmParsingUtilities.ReconstructPnpmDependencyPathV6("@babel/eslint-parser", "7.23.3").Should().BeEquivalentTo("/@babel/eslint-parser@7.23.3"); + pnpmParsingUtilities.ReconstructPnpmDependencyPath("@babel/eslint-parser", "7.23.3").Should().BeEquivalentTo("/@babel/eslint-parser@7.23.3"); // With peer deps: - PnpmParsingUtilities.ReconstructPnpmDependencyPathV6("mocha-json-output-reporter", "2.1.0(mocha@10.2.0)(moment@2.29.4)").Should().BeEquivalentTo("/mocha-json-output-reporter@2.1.0(mocha@10.2.0)(moment@2.29.4)"); + pnpmParsingUtilities.ReconstructPnpmDependencyPath("mocha-json-output-reporter", "2.1.0(mocha@10.2.0)(moment@2.29.4)").Should().BeEquivalentTo("/mocha-json-output-reporter@2.1.0(mocha@10.2.0)(moment@2.29.4)"); // Absolute path: - PnpmParsingUtilities.ReconstructPnpmDependencyPathV6("events_pkg", "/events@3.3.0").Should().BeEquivalentTo("/events@3.3.0"); + pnpmParsingUtilities.ReconstructPnpmDependencyPath("events_pkg", "/events@3.3.0").Should().BeEquivalentTo("/events@3.3.0"); } }