Nuget package references in .NET (Framework and Core)

.NET Software Composition Analysis

.NET developers are spoilt for choice when it comes to third party packages that are available to use in their solutions. With over 250k unique NuGet packages available for various purposes ranging from standard cross-cutting concerns such as logging, caching and error handling; through to more specific use cases such as generating PDFs, working with JSON data, or using Azure resources, packages can make the life of a developer much easier and more efficient. With so many choices, it is not uncommon to see a .NET solution with 20, 50 or even 100+ packages referenced.

While this is convenient for developers, it can be challenging to keep track of all these packages, the licenses, current and latest versions, and any known vulnerabilities. Visual Studio does allow you to see some of this information, however this can be a time-consuming activity, particularly challenging if your solution is continuing to evolve and when working with a team of developers.

I recently took on the challenge of finding a more reliable solution for software composition analysis and documentation of the packages the team were using in our solutions. After some research I came across the concept of the “Software Bill of Materials”. In this blog I cover what a Software Bill of Materials is and how we were able to use this to not only extract license details from our solution, but also to regularly scan our solution for new vulnerabilities in our build pipelines.

The term Software Bill of Materials comes from the manufacturing term Bill of Materials, both serve the purpose of keeping a list of the materials used to create a product. In software development, these materials can be libraries, firmware, frameworks, files and more.

Generating a Software Bill of Materials

Through my research I came across CycloneDX, an open-source tool designed to generate lightweight Software Bill of Materials specifications.

CycloneDX can generate these specifications for various types of projects, including Node.js, Python, Go, and .NET (Framework and Core). I was interested in their .NET module for our .NET Framework and .NET Core solutions.

The process was a lot easier than I expected, I was able to quickly install and generate a Software Bill of Materials specification for a few of my solutions.

Installing the tool is simple, before you can start you will need .NET Core 2.1, .NET Core 3.1 or .NET Core 5.0 installed on your development machine or build agent first. Once you have .NET Core installed, you can run the following command to get the latest version of the tool:

dotnet tool install –global CycloneDX

Once the tool is installed, you can quickly generate a Software Bill of Materials specification by executing something like the following, specifying the path to you solution file and -o for the output path for the specification (refer to the documentation for the complete set of options):

dotnet CycloneDX c:\tmp\MyProject\MyProject.sln -o ‘c:\tmp\SBOM’ 

The command outputs an xml file with the name bom.xml. The file contains information on all the components that make up your solution, for example in one solution we use AutoMapper. The XML below shows we are using version 9.0.0, the publisher is Jimmy Bogard and the MIT license applies to the package:


					<component type=library>
   <publisher>Jimmy Bogard</publisher>
   <description>A convention-based object-object mapper.</description>
      <hash alg=SHA-512>C53F15D5C107BA6E7564A5D6792952DAB4FC7C21E62D6A413C2F994C98D0F423BD8F5A41ED9533F8C8CDC7D3C83D0C172C5AE400D5EF5B283678A477C7CAAF4A</hash>
      <reference type=website>
      <reference type=vcs>


Analysing your Software Bill of Materials

The Software Bill of Materials specification can be imported into other tools to identify risks in software, including vulnerability identification, license compliance and outdated component analysis. There are a variety of tools available, I used OWASP’s DependencyTrack product which is an open-source software composition analysis platform. Following their documentation, I created a new project for each of my solutions, imported the Software Bill of Materials specification, and DependencyTrack ran analysis checking for license types, known vulnerabilities, and indicating whether components were current or not.

After importing the Software Bill of Materials specification generated earlier into DependencyTrack, I can get a quick overview of the state of the project. I can quickly see there are 364 dependencies in my solution, and 3 critical vulnerabilities.

DependencyTrack allows me to drill into the Dependencies and Audit tabs to see more information which compliments the information in the Software Bill of Material specification.

On the Audit tab the vulnerabilities are summarised for each component and can be further drilled into to see more information, add notes, and flag any false positives. DependencyTrack supports integrating with multiple sources of vulnerability intelligence, I configured it to check for known vulnerabilities in the Sonatype’s OSS Index.

The Dependencies tab shows a summary of all components in the solutions including name, version, license, count of vulnerabilities, a risk score and any outdated packages. The following example shows the AutoMapper library shown earlier is flagged as an outdated component:

Each time a report is published, the history of components and vulnerabilities is updated and can be viewed in various charts in the tool, giving you a comprehensive view over time as new vulnerabilities are discovered, and previous vulnerabilities are resolved.

Automating for Continuous Software Composition Analysis

CycloneDX is now integrated into our build pipelines: each time we build any of our components we generate a Software Bill of Material specification and include it alongside the build artifact to be manually uploaded into DependencyTrack for analysis.

In the coming months we plan to automatically publish these Software Bill of Material specifications to DependencyTrack using cURL and configure DependencyTrack to send notifications about the presence of newly discovered vulnerabilities via various channels including Teams, Slack, email and webhook.

These final changes will provide us with a robust and reliable method to keep track of all the packages used in our solutions along with their corresponding licenses, current and latest versions, and any known vulnerabilities much earlier and more accurately than we have done in the past.