Securing .NET Applications: Preventing Threats Through Package Audits

Article Banner
Author(s): Ajay kumar
Published On: 22 Mar 2025

Summary


Lets start this article with a few important questions !

  • Have you ever faced a production issue due to a vulnerable package?
  • Are you confident your CI/CD pipeline can catch outdated or risky dependencies?
  • How do you currently monitor package vulnerabilities in your projects?

These are critical questions every developer and team should ask themselves. Addressing these concerns proactively can save you from potential security breaches and ensure the reliability of your applications.

We often trust third-party NuGet packages to accelerate development—but with that trust comes risk. Many of these packages may carry known security vulnerabilities, and if left unchecked, they can become a backdoor into your application. This is where vulnerability detection in .NET projects becomes critical.

Starting with .NET SDK 5.0.200, Microsoft introduced a built-in auditing command:

Try running the below command in your dotnet project and see what happens


dotnet list package --vulnerable
        
Code Sample #1 : Command to check for vulnerable packages

This command scans both direct and transitive NuGet dependencies for known security issues using Microsoft’s advisory database. It flags packages with vulnerabilities, categorizing them by severity (Low to Critical), and provides advisory URLs to investigate further.

But detection is only step one.

Vulnerability checks should be automated into your build or deployment workflows. Failing a build when vulnerabilities are found prevents insecure code from reaching production. Simple shell or PowerShell scripts can be used to enforce this in local or CI pipelines without relying on GitHub or external tools.

Equally important is the role of the .csproj file—this file acts as the source of truth for all your package references. A single vulnerable package listed here, directly or indirectly, can compromise your entire application.

NugetAudit to the rescue!


NuGet 6.8 introduced the NuGetAudit MSBuild property, which enhances vulnerability detection during restore/build time. When set to true, NuGetAudit performs an audit of your project's NuGet dependencies and generates warnings for any detected vulnerabilities. This allows you to identify and address security issues before your application is deployed.

We are using a sample repo here which which uses below packages

  • Refit version 7.2.1 which has Critical vulnerability
  • Newtonsoft.Json version 12.0.3 which has High vulnerability

To enable NuGetAudit, we can add the following to our .csproj file:


<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <TargetFramework>net8.0</TargetFramework>
        <ImplicitUsings>enable</ImplicitUsings>
        <Nullable>enable</Nullable>
        <NugetAudit>true</NugetAudit>
    </PropertyGroup>

    <ItemGroup>
      <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
      <PackageReference Include="Refit" Version="7.2.1" />
    </ItemGroup>
</Project>
        
Code Sample #2 : Example .csproj file with NuGetAudit enabled

When NuGetAudit is enabled, the build process will generate warnings for any NuGet packages with known vulnerabilities. These warnings will include information about the vulnerability, such as the severity and the affected package version.

You can configure the level of detail in the NuGet audit warnings by using the NuGetAuditLevel property. This property accepts the following values:

  • None: No audit warnings are displayed.
  • Low: Only warnings for vulnerabilities with a severity of Low or higher are displayed. This is default value.
  • Moderate: Only warnings for vulnerabilities with a severity of Moderate or higher are displayed.
  • High: Only warnings for vulnerabilities with a severity of High or Critical are displayed.
  • Critical: Only warnings for vulnerabilities with a severity of Critical are displayed.

Lets explore some more scenarios


Disabling the audit mode

When We disbale the auditing by setting NuGetAudit To false and try to build / restore


<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <TargetFramework>net8.0</TargetFramework>
        <ImplicitUsings>enable</ImplicitUsings>
        <Nullable>enable</Nullable>
        <NugetAudit>false</NugetAudit>
    </PropertyGroup>

    <ItemGroup>
      <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
      <PackageReference Include="Refit" Version="7.2.1" />
    </ItemGroup>
</Project>
        
Code Sample #2 : Example .csproj file with NuGetAudit disabled

Build passed
Figure 1 : Build passed
Enabling the audit mode

Lets enable the auditing by setting NuGetAudit To true and try to build / restore


<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <TargetFramework>net8.0</TargetFramework>
        <ImplicitUsings>enable</ImplicitUsings>
        <Nullable>enable</Nullable>
        <NugetAudit>true</NugetAudit>
    </PropertyGroup>

    <ItemGroup>
      <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
      <PackageReference Include="Refit" Version="7.2.1" />
    </ItemGroup>
</Project>
        
Code Sample #3 : Example .csproj file with NuGetAudit enabled

Build passed with warnings
Figure 2 : Build passed with warnings

As we can see the build is warning about both the critical and high severity level packages.

Depending on security guidelines we may want to only flag certain severity level

Setting the severity level

Depending on security guidelines for out project we may want to only flag certain severity level and above. For this article lets assume, we only want to warn about critial vulnerabilities and leave the rest.

Lets set the severity level for our audit by setting NuGetAudit To true and try to build / restore


<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <TargetFramework>net8.0</TargetFramework>
        <ImplicitUsings>enable</ImplicitUsings>
        <Nullable>enable</Nullable>
        <NugetAudit>true</NugetAudit>
        <NugetAuditLevel>critical</NugetAuditLevel>
    </PropertyGroup>

    <ItemGroup>
      <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
      <PackageReference Include="Refit" Version="7.2.1" />
    </ItemGroup>
</Project>
        
Code Sample #4 : Example .csproj file with NugetAuditLevel defined

Build passed with critical severity level warnings
Figure 3 : Build passed with critical severity level warnings

As we can see the build is warning about only the critical severity level package(s).

Enforcing build failure for vulnerabilities

Now, warning are good but they can be ignored/missed allowing vulnerabilities to creep into the production code. To prevent this, there is another msbuild property WarningsAsErrors that can help by treating specified warnings codes as errors resulting in build failure. Refer the below table to such warning codes

Warning Code Reason
NU1900 Error communicating with package source, while getting vulnerability information.
NU1901 Package with low severity detected
NU1902 Package with moderate severity detected
NU1903 Package with high severity detected
NU1904 Package with critical severity detected
NU1905 An audit source does not provide a vulnerability database

Lets set critical warning as error for our audit by setting WarningsAsErrors To true and try to build / restore


<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <TargetFramework>net8.0</TargetFramework>
        <ImplicitUsings>enable</ImplicitUsings>
        <Nullable>enable</Nullable>
        <NugetAudit>true</NugetAudit>
        <NugetAuditLevel>critical</NugetAuditLevel>
        <WarningsAsErrors>NU1904;</WarningsAsErrors>
    </PropertyGroup>

    <ItemGroup>
      <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
      <PackageReference Include="Refit" Version="7.2.1" />
    </ItemGroup>
</Project>
        
Code Sample #5 : Example .csproj file with WarningsAsErrors defined

Build failure with critical vulnerability
Figure 4 : Build failure with critical vulnerability

As we can see the build is warning about only the critical severity level package(s).

Conclusion


In conclusion, vulnerability detection in .NET projects is a critical aspect of modern software development. By leveraging the built-in auditing command and the NuGetAudit MSBuild property, developers can proactively identify and address security vulnerabilities in their applications. This not only helps to protect sensitive data but also ensures compliance with security standards and best practices.

By integrating these tools into your development workflow, you can significantly reduce the risk of security breaches and enhance the overall security posture of your .NET applications.

Integrating these tools into your CI/CD build pipelines ensures that vulnerabilities are detected and addressed early, preventing insecure code from being deployed to production systems.


Thats about it for this article. Hope you liked it.

Thanks for reading through. Please share feedback, if any, in comments or on my email ajay.a338@gmail.com

Copyright © 2025 Dev Codex

An unhandled error has occurred. Reload 🗙