Microsoft

NuGet Package Pruning in .NET 10: dipendenze più pulite e meno falsi positivi di vulnerabilità

Dario Fadda Giugno 8, 2026

Se hai mai eseguito dotnet list package --vulnerable su un progetto .NET, probabilmente hai visto avvisi per pacchetti transitivi che non hai mai installato esplicitamente — come System.Text.Json o System.Formats.Asn1. In molti casi, questi pacchetti sono già forniti in una versione più recente dal runtime .NET, e gli avvisi sono falsi positivi. Con .NET 10, NuGet risolve questo problema in modo elegante: il package pruning.

Il problema: dipendenze transitorie fantasma

Molte librerie su NuGet.org hanno come target netstandard2.0 per massima compatibilità, e portano con sé dipendenze da pacchetti come System.Memory, System.Text.Json o System.IO.Pipelines — pacchetti che nel frattempo sono diventati parte delle .NET Runtime Libraries.

Il risultato pratico: un progetto .NET 10 che dipende da una di queste librerie si trova a risolvere durante il restore System.Text.Json 8.0.0 come dipendenza transitiva, anche se il runtime .NET 10 già include una versione più recente. Quando viene pubblicata una CVE contro quella versione, i vulnerability scanner la segnalano — anche se la tua applicazione non la usa affatto.

Questo genera tre problemi concreti:

  • Falsi positivi nelle vulnerability scan: avvisi per pacchetti già coperti dal runtime
  • Grafi di restore più grandi: più pacchetti da risolvere e scaricare
  • Riferimenti obsoleti: entry vecchie nel dependency graph che non rispecchiano cosa usa davvero l’app

Come funziona il Package Pruning

Il package pruning rimuove dal grafo di dipendenze NuGet i pacchetti già forniti dalle .NET Runtime Libraries al momento del restore. Il .NET SDK include una lista dei pacchetti forniti da ciascun target framework, con la versione massima disponibile. Se una dipendenza transitiva rientra in quel range, NuGet la elimina.

Ad esempio, net10.0 include System.Text.Json 10.x: una dipendenza transitiva su System.Text.Json 9.0.0 verrebbe pruned; una su System.Text.Json 11.0.0 no (perché il runtime non copre quella versione).

Prima del pruning

Sample.csproj : warning NU1903: Package 'System.Formats.Asn1' 6.0.0 has a
known high severity vulnerability

Project 'Sample' has the following package references
   [net10.0]:
   Top-level Package              Resolved
   > Microsoft.Extensions.AI      10.0.1
   > NuGet.Protocol               6.9.1

   Transitive Package                                     Resolved
   > System.Diagnostics.DiagnosticSource                  10.0.0
   > System.Formats.Asn1                                  6.0.0   ← VULNERABILE
   > System.Text.Json                                     10.0.0
   > System.Threading.Channels                            10.0.0
   ...

Dopo il pruning

Project 'Sample' has the following package references
   [net10.0]:
   Top-level Package              Resolved
   > Microsoft.Extensions.AI      10.0.1
   > NuGet.Protocol               6.9.1

   Transitive Package                                     Resolved
   > Microsoft.Extensions.AI.Abstractions                 10.0.1
   > Newtonsoft.Json                                      13.0.3
   > NuGet.Common                                         6.9.1
   ...
   (System.Formats.Asn1, System.Text.Json, System.Threading.Channels rimossi)

System.Formats.Asn1, System.Text.Json e System.Threading.Channels non compaiono più come dipendenze transitorie perché sono ridondanti su net10.0. L’avviso di vulnerabilità scompare.

Le novità in .NET 10

Il package pruning era disponibile come opt-in dal .NET SDK 9.0.200. Con .NET 10 diventa il comportamento predefinito per i progetti che hanno come target net10.0 o versioni successive.

In parallelo, NuGetAuditMode ora vale all per default, estendendo l’audit alle dipendenze transitorie. Pruning e audit lavorano insieme: il pruning rimuove i pacchetti ridondanti, l’audit si concentra sulle dipendenze che la tua app usa davvero.

I risultati misurati dal team NuGet:

  • 70% di report di vulnerabilità transitorie in meno rispetto ai default precedenti
  • Fino al 50% di riduzione del tempo di restore a livello di singolo progetto
  • Tasso di successo del restore misurabilmente più alto

Gestione dei PackageReference diretti

Se hai un riferimento diretto a un pacchetto che rientra nel range del pruning, NuGet non lo rimuove automaticamente dal tuo .csproj, ma lo “privatizza” aggiungendo implicitamente PrivateAssets='all' e IncludeAssets='none'. Quando un riferimento diretto può essere rimosso completamente, NuGet emette il warning NU1510:

<!-- Prima: riferimento diretto ridondante -->
<PackageReference Include="System.Text.Json" Version="10.0.0" />

<!-- NuGet emetterà NU1510: puoi rimuovere questo riferimento -->

Come attivare manualmente (per progetti precedenti)

Per progetti che non usano ancora i default di .NET 10, è possibile attivare pruning e audit esplicitamente:

<PropertyGroup>
  <NuGetAuditMode>all</NuGetAuditMode>
  <RestoreEnablePackagePruning>true</RestoreEnablePackagePruning>
</PropertyGroup>

In un progetto multi-target, se almeno un target framework è net10.0 o successivo, il pruning si applica a tutti i target framework del progetto.

Impatto su pipeline CI/CD e security scanning

Per i team che usano tool come OWASP Dependency-Check, Snyk, GitHub Dependabot o dotnet-outdated, il package pruning riduce significativamente il rumore nei report. I vulnerability report post-pruning riflettono le dipendenze reali dell’applicazione, rendendo le decisioni di remediation più precise e il triage più veloce.

Il comando per verificare lo stato attuale del tuo progetto:

dotnet list package --include-transitive --vulnerable

Con .NET 10 e pruning attivo, l’output dovrebbe essere significativamente più corto rispetto a .NET 8/9 con gli stessi package di primo livello.

Conclusione

Il package pruning in .NET 10 è uno di quei miglioramenti silenziosi che hanno un impatto concreto quotidiano: meno rumore nei report di sicurezza, restore più veloci, e un dependency graph che rispecchia davvero cosa usa la tua applicazione. Se stai ancora su .NET 9, vale la pena attivarlo subito con le due property nella sezione precedente.

Fonte: NuGet Package Pruning: Cleaner Dependencies and Actionable Vulnerability Reports — .NET Blog

💬 Unisciti alla discussione!


Questo è un blog del Fediverso: puoi trovare quindi questo articolo ovunque con @blog@spcnet.it e ogni commento/risposta apparirà qui sotto.

Se vuoi commentare su NuGet Package Pruning in .NET 10: dipendenze più pulite e meno falsi positivi di vulnerabilità, utilizza la discussione sul Forum.
Condividi la tua esperienza, confrontati con altri professionisti e approfondisci i dettagli tecnici nel nostro 👉 forum community