How .NET 10's NuGet Package Pruning Eliminates False Vulnerability Warnings
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.

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.

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.
Related Articles
- Intuit Enterprise Suite vs QuickBooks Online: 8 Key Differences You Should Know
- Breathing New Life into a 1947 Arvin 664A AM Radio: A Restoration Journey
- GitHub Patches Critical RCE Bug in Git Push Pipeline – Zero-Day Exploit Prevented
- 7 Critical Steps to Fortify Your Enterprise Against AI-Powered Vulnerability Discovery
- Lessons from the Snowden Leaks: A CISO's Guide to Preventing Insider Threats and Managing Media Fallout
- Defend Against the CopyFail Linux Vulnerability: A Step-by-Step Guide
- Killswitch Proposal Offers Emergency Patch for Kernel Vulnerabilities
- The Fall of a Cyber Thief: 10 Key Facts About the 'Scattered Spider' Member Who Pleaded Guilty