Contributing expert: Michael Pozhigan,
ASP.NET Core Back-end Web Developer at Coherent Solutions
NuGet Audit in .NET 9+ is a surprisingly powerful security scanner already running in your builds. Here's how to use it.
Summary: NuGet Audit is built into .NET 8+ and requires zero setup to start scanning your dependencies. .NET 9 adds transitive checks, and .NET 10 adds auto-fixing of direct vulnerabilities. With two small config tweaks, you can make critical vulnerabilities automatically break your build.
Every dependency you add to an app is a potential attack surface. Yet most .NET teams rely on a third-party SaaS scanner for security or do nothing at all. There’s a better solution — a solid security scanner, NuGet Audit, has been quietly bundled into the .NET SDK since version 8, and all you need to do is configure it properly.
What NuGet offers out of the box
NuGet Audit runs automatically on every restore and build. It checks your dependencies against the GitHub Advisory Database (the same source powering GitHub's security alerts) and issues warnings for any known vulnerabilities it finds. You can also trigger it explicitly from the CLI whenever you want with the following command:
The NuGet Audit capabilities you’re able to access depend on your SDK version:

.NET 10 adds automatic remediation through the dotnet package update --vulnerable command. When vulnerable direct dependencies are detected, NuGet can automatically update them to a secure version. Transitive dependencies are not updated, however, so some issues may still require manual investigation.
Teams should be aware that, for .NET 9, transitive scanning is an optional feature that must be enabled. Without it, NuGet Audit only checks packages you reference directly and may miss vulnerabilities introduced deeper in the dependency tree. There are two ways to turn transitive scanning on:
-
Add –include-transitive to your CLI commands.
-
Set it globally in Directory.Build.props, so that it runs automatically for everyone on the team. Here’s how:
<PropertyGroup>
<!-- Possible values: 'direct' (default in .NET 9) or 'all' (default in .NET 10+) -->
<NuGetAuditMode>all</NuGetAuditMode>
</PropertyGroup>
</Project>
Three important NuGet config tweaks
NuGet Audit works out of the box, but its default configuration is intentionally conservative. To get the most value from it, there are three changes worth making: standardize audit settings across the team, make serious vulnerabilities break the build, and run audits in CI to detect newly disclosed CVEs.
1. Commit a shared nuget.config
Microsoft recommends committing a nuget.config to your repository root. This guarantees that every developer and CI runner uses the exact same package sources, preventing accidental fallbacks to a locally misconfigured feed. If you use a private NuGet feed, however, there's a catch: vulnerability data won't be available from that feed. To ensure availability, you can use the following config sections to add nuget.org as an explicit audit source, separate from your regular package sources:
<clear/>
<add key="my-private-feed" value="https://my-private-feed/index.json" />
</packageSources>
<auditSources>
<clear/>
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
</auditSources>
2. Make critical vulnerabilities break the build
By default, NuGet Audit only generates warnings. Warnings are easy to ignore, especially when a project has a lot of them. The fix is to promote high and critical-severity warnings to errors. To do this, add a command to your Directory.Build.props so it applies across every project in the solution:
<WarningsAsErrors>NU1900;NU1903;NU1904</WarningsAsErrors>
<!-- NU1900 = NuGet audit unavailable, break build
NU1901 = Low severity,
NU1902 = Medium severity,
NU1903 = High severity, break build
NU1904 = Critical severity, break build-->
</PropertyGroup>
Tip: Including NU1900 will fire when the audit itself fails to run (caused by network issues, bad configs, etc.). A silent audit failure is the same as no audit at all, so you will be notified.
3. Use it in CI
Your local build will enforce the rules above, but you also want a scheduled pipeline that catches vulnerabilities in already-deployed solutions, even when no code has changed. After all, a new CVE can appear today and affect the code you shipped six months ago.
The solution — add a minimal step in Bitbucket Pipelines (the same will work in GitHub Actions or Azure Pipelines):
default:
- step:
name: Restore and Audit NuGet Packages
script:
# Restore contains NuGet audit
# Mark High(NU1903) and Critical(NU1904) NuGet vulnerabilities as errors
# Mark Unavailable Audit (NU1900) as an error
- dotnet restore /p:WarningsAsErrors=NU1900%3BNU1903%3BNU1904
Is NuGet Audit’s security enough?
You might be wondering if NuGet Audit is enough to secure your build. While it has limitations, it’s a bare-minimum security measure that teams should implement. The scanner covers your entire NuGet dependency tree, uses a well-maintained advisory database, and requires nothing beyond the SDK you already have. Here are a few of the NuGet Audit limitations you should be aware of:
-
Single source to check vulnerabilities (GitHub Advisory Database ).
-
Security scanning solely for NuGet packages — does not extend to containers, npm, or IaC.
-
No automated PR creation for fixes.
If your team requires any of these features, you should consider using another tool such as Dependabot, Renovate, or Snyk, in addition to NuGet Audit.
NuGet configuration reminders
-
Enable transitive scanning by adding --include-transitive or setting it globally in Directory.Build.props.
-
Commit a shared nuget.config with an explicit <auditSources> command if you use a private feed.
-
Promote NU1900, NU1903, and NU1904 to errors so that high and critical vulnerabilities break the build.
- Set up a scheduled CI pipeline to catch new CVEs in already-deployed code.
Security beyond NuGet
Once you’ve made the suggested config tweaks, consider using additional tools if you have higher security requirements or would like the benefit of automated PR creation.
-
Enabling Dependabot on GitHub only requires a single checkbox and creates automated PRs for package updates.
-
Tools such as Renovate or Snyk can help automate dependency PRs on Azure DevOps or Bitbucket.
While NuGet Audit won't replace a full security auditing tool, it's an easy first step you can take right now to stop shipping solutions with vulnerable .NET packages. It’s an oft-overlooked tool that only requires a few simple tweaks to increase its effectiveness and create a baseline layer of security.