Checking your solution for NuGet vulnerabilities or deprecated packages

02/05/2024
Nuget.NET

While your software might be the best in the world, it's only as good as the libraries it uses. In this small blog post, we will discover how to check your solution for NuGet vulnerabilities or deprecated packages.

Motivation

You might check your own code for common issues like Cross-Site Scripting (XSS), SQL Injection, etc. But what about the libraries you use? They might have vulnerabilities or be deprecated. Attackers could use a supply chain attack to inject malicious code into your software.

What is a supply chain attack?

A supply chain attack is a cyber-attack that seeks to damage an organization by targeting less-secure elements in the supply chain, like, say, a third-party package.

NuGet to the rescue

Since some versions (.NET 5 SDK), NuGet will report vulnerabilities and deprecated packages on their website and, of course, also via the CLI. And this is what we will use in this blog post. We can leverage the dotnet CLI to check for vulnerabilities and deprecated packages.

Let's create a simple project like this:

<Project Sdk="Microsoft.NET.Sdk">

    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>net8.0</TargetFramework>
    </PropertyGroup>

    <ItemGroup>
      <PackageReference Include="System.Data.SqlClient" Version="4.8.5" />
    </ItemGroup>

</Project>

System.Data.SqlClient in Version 4.8.5 has a known vulnerability. If you go to the NuGet website, it looks like this:

Nuget Website

So, the website tells us that there is a vulnerability in this package and there might be a newer version available.

If we do the same with the CLI:

dotnet list package --vulnerable

This will result in:

The following sources were used:
   https://api.nuget.org/v3/index.json
   https://ci.appveyor.com/nuget/benchmarkdotnet

Project `Vulnerable` has the following vulnerable packages
   [net8.0]: 
   Top-level Package            Requested   Resolved   Severity   Advisory URL                                     
   > System.Data.SqlClient      4.8.5       4.8.5      High       https://github.com/advisories/GHSA-98g6-xh36-x2p7

We could leverage that in a CI/CD pipeline to check for vulnerabilities and fail the build if there are any. Currently, the CLI always returns 0 as an exit code, so we have to parse the output to check for vulnerabilities. There is a ticket on GitHub to address that issue: https://github.com/NuGet/Home/issues/11315

If you do feel it is worth having, give the ticket a thumbs up. Alternatively, you can utilize tools like grep in your CI pipeline. Here is an example of how to do that with GitHub Actions:

- name: Check for vulnerable packages
  run: |
    set -e # This will cause the script to exit on the first error
    OUTPUT=$(dotnet list package --vulnerable)
    echo "$OUTPUT"
    if echo "$OUTPUT" | grep -q 'no vulnerable packages'; then
      echo "No vulnerable packages found"
    else
      if echo "$OUTPUT" | grep -q 'vulnerable'; then
        echo "Vulnerable packages found"
        exit 1
      fi
    fi

If you have a project with the name Vulnerable, then you have to specify a bit more of the error string, as also project names are printed to the console, which will lead to a failure if you have "MyAssembly.Vulnerable.csproj".

More things you can do

It doesn't stop here - you can also check for vulnerabilities in the dependencies of your dependencies. This is especially important if you use a lot of third-party packages.

dotnet list package --vulnerable --include-transitive

Last but not least, you can also check for deprecated packages:

dotnet list package --deprecated

Conclusion

Keep track of your dependencies. It is important to keep them up-to-date!

6
An error has occurred. This application may no longer respond until reloaded. Reload x