Auditing Packages for Vulnerabilities

This section documents MSBuild 18.9, the .NET SDK 10.0.402 (with its dotnet CLI) and NuGet 7.9, as published in the MSBuild, .NET and NuGet documentation on learn.microsoft.com, which is the reference these pages are written and verified against. Material about .NET 11 / NuGet 8.0 is still in preview and is always flagged as such — never presented as baseline.

This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production.

The C# Reference bibliography lists the reference material consulted while preparing these pages.

Every restore can check the resolved packages against a database of known vulnerabilities and report each hit as a warning. NuGetAudit has done this for PackageReference projects since NuGet 6.8 (.NET 8 SDK), using advisories from the GitHub Advisory Database that nuget.org publishes in its vulnerability resource. This page runs it on an old version of NuGet.Protocol with NuGet 7.9.0 (.NET SDK 10.0.402).

A restore with known vulnerabilities

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net10.0</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="NuGet.Protocol" Version="5.11.2" />
  </ItemGroup>
</Project>
dotnet restore --force
~/audit/Audit.csproj : warning NU1901: Package 'NuGet.Packaging' 5.11.2 has a known low severity vulnerability, https://github.com/advisories/GHSA-g4vj-cjjj-v7hg
~/audit/Audit.csproj : warning NU1901: Package 'NuGet.Protocol' 5.11.2 has a known low severity vulnerability, https://github.com/advisories/GHSA-g4vj-cjjj-v7hg
~/audit/Audit.csproj : warning NU1903: Package 'Newtonsoft.Json' 9.0.1 has a known high severity vulnerability, https://github.com/advisories/GHSA-5crp-9r3c-p9vr
~/audit/Audit.csproj : warning NU1903: Package 'NuGet.Common' 5.11.2 has a known high severity vulnerability, https://github.com/advisories/GHSA-6qmf-mmc7-6c2p
~/audit/Audit.csproj : warning NU1903: Package 'NuGet.Protocol' 5.11.2 has a known high severity vulnerability, https://github.com/advisories/GHSA-6qmf-mmc7-6c2p
~/audit/Audit.csproj : warning NU1903: Package 'NuGet.Protocol' 5.11.2 has a known high severity vulnerability, https://github.com/advisories/GHSA-g3q9-xf95-8hp5
~/audit/Audit.csproj : warning NU1904: Package 'NuGet.Packaging' 5.11.2 has a known critical severity vulnerability, https://github.com/advisories/GHSA-68w7-72jg-6qpp

One direct reference produced seven warnings, four of them for packages the project never named: NuGet.Packaging, NuGet.Common and Newtonsoft.Json 9.0.1 arrive transitively. The code encodes the severity:

Code Meaning

NU1900

The audit could not run (a source failed to provide vulnerability data, for example)

NU1901

low severity

NU1902

moderate severity

NU1903

high severity

NU1904

critical severity

NU1905

an audit source provides no vulnerability data

No advisory against the NuGet.Protocol 5.11.2 graph is rated moderate, so NU1902 did not appear above. A second project with the same layout that references System.Security.Cryptography.Xml 4.5.0 instead (and nothing else) shows one:

<PackageReference Include="System.Security.Cryptography.Xml" Version="4.5.0" />
  Determining projects to restore...
~/audit/Audit.csproj : warning NU1902: Package 'System.Security.Cryptography.Xml' 4.5.0 has a known moderate severity vulnerability, https://github.com/advisories/GHSA-vh55-786g-wjwj
  Restored ~/audit/Audit.csproj (in 424 ms).

Configuring the audit

Property Default Values

NuGetAudit

true

false turns auditing off

NuGetAuditMode

all for net10.0+, otherwise direct

direct (top-level packages) or all (transitive too)

NuGetAuditLevel

low

lowest severity reported: low, moderate, high, critical

NuGetAuditSuppress (item)

 — 

an advisory URL to ignore

The same project with other settings:

  • -p:NuGetAuditLevel=high — the two low-severity warnings disappeared; four NU1903 and one NU1904 remained.

  • -p:NuGetAuditMode=direct — only the three advisories for NuGet.Protocol itself remained; the critical one in NuGet.Packaging vanished from the output.

  • An advisory accepted after review is suppressed by URL:

    <ItemGroup>
      <NuGetAuditSuppress Include="https://github.com/advisories/GHSA-5crp-9r3c-p9vr" />
    </ItemGroup>

    after which the restore no longer mentioned GHSA-5crp.

The mode default has a history worth knowing. The NuGet 6.12 notes describe transitive auditing as the new default; that was reverted to direct in SDK 9.0.101; and all became the default only for projects targeting net10.0 or later with NuGet 7.0 (.NET 10 SDK). A net8.0 project restored with SDK 10 still audits only direct references unless NuGetAuditMode is set — set it explicitly in Directory.Build.props.

Audit sources

The vulnerability data comes from the audit sources: the auditSources section of nuget.config, or, when there is none, the package sources themselves. A repository that restores only from an internal mirror or a folder therefore gets no audit at all — silently. A project referencing Newtonsoft.Json 9.0.1 from a folder feed:

== no audit source
  Restored ~/audit2/A.csproj (in 181 ms).
== with auditSources
~/audit2/A.csproj : warning NU1903: Package 'Newtonsoft.Json' 9.0.1 has a known high severity vulnerability, https://github.com/advisories/GHSA-5crp-9r3c-p9vr
  Restored ~/audit2/A.csproj (in 1.18 sec).

The second run added nuget.org’s vulnerability-only endpoint, which serves advisories but no packages — acceptable to networks that block package downloads from nuget.org:

<auditSources>
  <clear />
  <add key="nuget.org-vulns" value="https://data.nuget.org/v3/index.json" />
</auditSources>

NU1905 is raised only when a configured audit source has no data; with no auditSources section, package sources without data are skipped without a warning — which is what happened in the first run.

Finding and fixing

dotnet package list --vulnerable --include-transitive lists every vulnerable package with its advisories:

Project `Audit` has the following vulnerable packages
   [net10.0]:
   Top-level Package      Requested   Resolved   Severity   Advisory URL
   > NuGet.Protocol       5.11.2      5.11.2     High       https://github.com/advisories/GHSA-g3q9-xf95-8hp5
                                                 High       https://github.com/advisories/GHSA-6qmf-mmc7-6c2p
                                                 Low        https://github.com/advisories/GHSA-g4vj-cjjj-v7hg

   Transitive Package      Resolved   Severity   Advisory URL
   > Newtonsoft.Json       9.0.1      High       https://github.com/advisories/GHSA-5crp-9r3c-p9vr
   > NuGet.Common          5.11.2     High       https://github.com/advisories/GHSA-6qmf-mmc7-6c2p
   > NuGet.Packaging       5.11.2     Critical   https://github.com/advisories/GHSA-68w7-72jg-6qpp
                                      Low        https://github.com/advisories/GHSA-g4vj-cjjj-v7hg

It still listed GHSA-5crp-9r3c-p9vr after the suppression above: suppressions apply to restore warnings, not to this report. dotnet nuget why <project> Newtonsoft.Json shows which top-level package pulls a transitive one in (Dependency Resolution).

dotnet package update --vulnerable (.NET 10) moves each vulnerable package to the lowest non-vulnerable version. Here it failed and changed nothing:

Updating packages with security advisories in ~/audit
error: NU1605: Warning As Error: Detected package downgrade: NuGet.Common from 5.11.7 to 5.11.5. Reference the package directly from the project to select a different version.
error:  Audit -> NuGet.Packaging 5.11.7 -> NuGet.Configuration 5.11.7 -> NuGet.Common (>= 5.11.7)
error:  Audit -> NuGet.Common (>= 5.11.5)
Preview restore with updated packages was not successful. Force mode is not yet available.

The per-package "lowest fixed version" choices were inconsistent with each other, and the resulting downgrade is NU1605, which the SDK always treats as an error; the dotnet package update page documents that warnings-as-errors can block the update and suggests a condition to relax them while updating. Updating the top-level package to a current release — or, for a transitive package, pinning a fixed version with Central Package Management’s transitive pinning (Central Package Management) — is the reliable fix.

In CI

Warnings scroll past; CI should fail on the severities you care about:

<PropertyGroup>
  <WarningsAsErrors>$(WarningsAsErrors);NU1903;NU1904</WarningsAsErrors>
</PropertyGroup>
~/audit/Audit.csproj : error NU1903: Warning As Error: Package 'NuGet.Common' 5.11.2 has a known high severity vulnerability, https://github.com/advisories/GHSA-6qmf-mmc7-6c2p

Because advisories are published continuously, a build of an unchanged commit can start failing overnight. The documentation suggests keeping audit warnings as warnings in the main build and running a dedicated audit pipeline on a schedule that fails on them, and checking that every project is actually restored (and so audited) by that pipeline.

Common mistakes

  • Relying on the net10.0 default in multi-targeted or older projects — set NuGetAuditMode explicitly.

  • A mirror-only nuget.config — no audit unless auditSources is configured.

  • Suppressing by package instead of by advisory — use NuGetAuditSuppress with the advisory URL, and record why.

  • Trusting dotnet package update --vulnerable blindly — it can fail or produce downgrades; review the result.