Package pruning drops packages from the restore graph when the .NET runtime already supplies them, such as an old System.Text.Json pulled in by a dependency. Fewer packages means fewer audit findings about code you never actually run. It is on by default for .NET 10 targets and opt in for .NET 9.
The problem
Libraries that support older frameworks often depend on packages that only matter for those frameworks. When your app targets a newer runtime, the platform already contains that functionality, and the assembly from the package is not used. Yet the package sits in your graph, and an audit with transitive checking can flag it.
Microsoft's PackageReference documentation uses System.Text.Json as the example: a project targeting .NET 9 or .NET 8 can still end up with an unneeded System.Text.Json 8.0.0 dependency.
How pruning works
| Package kind | What pruning does |
|---|---|
| Transitive, through another package or project | Removed from the graph, not downloaded |
| Direct package reference | PrivateAssets all and IncludeAssets none are applied |
| Direct reference that can be removed on .NET 10 | Warning NU1510 suggests deleting it |
| Project reference matching a pruned ID | Not pruned, warning NU1511 on .NET 10 |
The SDK supplies the list of prunable packages based on the shared frameworks in your project. You can see a message at detailed verbosity when a package is pruned for a given framework.
Availability
- Introduced with NuGet 6.13 and .NET SDK 9.0.200, first for transitive packages.
- From the .NET 10 SDK, pruning affects direct packages too.
- Opt in with the .NET 9 SDK using RestoreEnablePackagePruning set to true. Enabled by default for projects targeting .NET 10 or higher.
- It needs the default dependency resolver released in NuGet 6.12.
<PropertyGroup>
<RestoreEnablePackagePruning>true</RestoreEnablePackagePruning>
</PropertyGroup>
Effect on audit and lock files
Microsoft names two benefits: faster restores from smaller graphs, and fewer false positives from component scanners such as NuGet Audit. It is particularly useful with NuGetAuditMode set to all. Lock files change too. After enabling pruning on an existing project, the next lock file regeneration can show a larger than usual diff because pruned packages disappear.
A careful rollout
- Enable pruning in a branch and restore.
- Compare the audit warnings before and after, and record which packages vanished.
- Regenerate the lock file and review the diff.
- Run your tests, since pruning should not change runtime behavior, but verify.
- Treat any remaining finding on a pruned type of package as worth another look.
What pruning does not fix
It does not remove findings for packages you really use. A real vulnerable dependency stays in the graph. Pruning only trims what the runtime already covers.
Try it yourself
Click through it at your own pace, or open it full screen. See how removing findings that do not apply makes the remaining list easier to act on.
Safeguard's reachability analysis helps separate dependencies whose vulnerable code is used from those where it is not, and a free scan lets you try it.
Quick check
Is pruning on by default?
For projects targeting .NET 10 or higher with the .NET 10 SDK, yes. With the .NET 9 SDK it is opt in.
Will pruning hide a real vulnerability?
It removes only packages the runtime already provides. Packages you actually depend on stay in the graph.
Sources
- NuGet PackageReference in project files, Microsoft Learn
- Auditing package dependencies for security vulnerabilities, Microsoft Learn
Last reviewed: 19 October 2026.