How .NET 10's NuGet Package Pruning Eliminates False Vulnerability Warnings

By

Introduction

If you've ever run NuGet Audit or a vulnerability scanner on a .NET project, you've likely been flooded with warnings about transitive packages you never explicitly installed. These alerts often target well-known libraries like System.Text.Json or System.Text.Encodings.Web — packages that, in many cases, are already supplied at a newer, patched version by the .NET Runtime Libraries themselves. The result? A frustrating number of false positives that waste time and erode trust in automated scans.

How .NET 10's NuGet Package Pruning Eliminates False Vulnerability Warnings
Source: devblogs.microsoft.com

Starting with .NET 10, NuGet introduces package pruning — a feature that automatically removes these platform-provided transitive dependencies from the restore graph. Combined with a default NuGetAuditMode set to all, this approach cuts transitive vulnerability reports by a staggering 70% according to internal telemetry.

Let's dive into why this happens, how pruning works, and what it means for your projects.

The Problem: False-Positive Vulnerability Warnings

Modern .NET applications rely on a rich ecosystem of NuGet packages. Many of these packages, especially those targeting netstandard2.0 for maximum compatibility, still carry dependencies on libraries like System.Memory or System.Text.Json — packages that have since become part of the .NET Runtime Libraries. The platform evolution doesn't always keep pace: for instance, System.IO.Pipelines started as a standalone NuGet package and only later was folded into the runtime.

Consider a hypothetical .NET 10 project that depends on a library targeting netstandard2.0. That library might pull in System.Text.Json 8.0.0 as a transitive dependency — even though the .NET 10 runtime ships System.Text.Json 10.0.x natively. NuGet still resolves the older package from nuget.org, and when a CVE is published against version 8.0.0, vulnerability scanners flag it — even though your app never actually uses that old package. It's a classic false positive.

The core issues boil down to three points:

  • False-positive vulnerability warnings: A CVE against a platform-provided package triggers a warning even when the runtime includes a fix.
  • Larger restore graphs: Every transitive dependency adds download overhead, more entries in the resolution graph, and unnecessary noise.
  • Stale package references: Older, unsupported entries remain in the graph even though the application uses the in-box runtime implementation.

How Transitive Dependencies Accumulate

The journey to these false positives begins with compatibility. Libraries on nuget.org often target netstandard2.0 to support a broad range of .NET versions. As a result, they bring along dependencies that were once essential but are now baked into the runtime. This isn't limited to old packages either — as the platform evolves, packages that ship independently today may become part of the runtime tomorrow.

When you restore a project, NuGet resolves the full dependency graph, including every transitive package. The platform runtime libraries are not consulted during resolution; NuGet treats them as separate packages. So even though System.Text.Json is available in-box, NuGet downloads and includes the older version from nuget.org. The result is a polluted graph that triggers misleading alerts.

What Is Package Pruning?

Package pruning is a new restore-time optimization introduced in .NET 10. It automatically removes any package from the dependency graph that is already provided by the .NET Runtime Libraries. The .NET SDK maintains a list, per target framework, of which packages are considered platform-provided and the highest version available. If a transitive dependency falls within that version range, NuGet prunes it — entirely eliminating it from the resolved graph.

How .NET 10's NuGet Package Pruning Eliminates False Vulnerability Warnings
Source: devblogs.microsoft.com

For example, net8.0 includes System.Text.Json version 8.0.x. If your project targets net8.0 and a transitive dependency requests System.Text.Json 8.0.0, NuGet will prune it because the runtime already supplies an equal or higher version. However, if the transitive dependency requests 9.0.0, pruning does not apply — the runtime only provides up to 8.0.x, so the 9.0.0 package remains in the graph.

This simple rule has a profound effect: it reduces noise, shrinks restore graphs, and — most importantly — eliminates the false-positive vulnerability warnings for packages that your application never actually loads.

Real-World Impact: 70% Fewer Warnings

Telemetry from projects using the new defaults (pruning enabled and NuGetAudienceMode=all) shows a 70% reduction in transitive vulnerability reports compared to projects using previous settings. This isn't just about cleaner dashboards; it means developers can trust their vulnerability scans again. When a warning does appear, it's far more likely to represent a genuine threat that requires action.

Beyond security, pruning also improves build performance. Smaller restore graphs mean fewer packages to download, parse, and store. Teams working on large solutions with many dependencies will notice faster restore times and less disk usage.

Configuring NuGet Audit and Pruning

For .NET 10 projects, the new behavior is enabled by default. You don't need to change anything to benefit from pruning. NuGet Audit automatically runs during restore with NuGetAudienceMode set to all, which means all transitive dependencies are audited — but thanks to pruning, many of the historical false positives are gone.

If you need to disable pruning (not recommended), you can set the MSBuild property:

<PropertyGroup>
  <NuGetAudienceMode>direct</NuGetAudienceMode>
</PropertyGroup>

This reverts auditing to only direct dependencies, but you'll lose the smart pruning logic. Most teams should stick with the defaults.

Conclusion

.NET 10's NuGet package pruning is a quiet but powerful improvement. It solves a long-standing pain point for .NET developers: the false-positive vulnerability alerts that clutter security reports and waste valuable time. By removing platform-provided packages from the restore graph, pruning makes vulnerability reports actionable, reduces graph complexity, and speeds up restores — all while being completely automatic.

If you're upgrading to .NET 10, your builds will immediately benefit. Fewer warnings, cleaner dependency graphs, and more confidence in your security posture — that's a win for everyone.

Tags:

Related Articles

Recommended

Discover More

Red-Teaming Government AI Assistants: A Practical Guide to Uncovering Vulnerabilities in EduBotWhy I Ditched Chrome, Firefox, and Samsung Internet for a Hidden Gem on AndroidCambrian Fossil Discovery Reshapes Understanding of Early Animal Life5 Critical Lessons from the Retracted Instructure Data Breach ReportHarnessing Milwaukee's Latest Jobsite Power Solutions: A Comprehensive Guide