یکی از چالشهای همیشگی توسعهدهندگان .NET، مدیریت وابستگیها و برخورد با هشدارهای آسیبپذیری است. اغلب هنگام اجرای NuGet Audit یا اسکنرهای آسیبپذیری، با هشدارهایی مواجه میشویم که مربوط به بستههای گذرا (Transitive) هستند؛ بستههایی که مستقیماً نصب نکردهایم اما از طریق وابستگیهای دیگر وارد پروژه شدهاند. بسیاری از این هشدارها «مثبت کاذب» (False Positive) هستند، زیرا نسخه جدیدتر آن بستهها قبلاً توسط خود Runtime .NET فراهم شده است.
در .NET 10، مایکروسافت با معرفی ویژگی Package Pruning (هرس بستهها) و فعالسازی پیشفرض وابستگیهای گذرا، گام مهمی در حل این مشکل برداشتهاست. این ویژگی نه تنها گزارشهای غیرضروری را به شدت کاهش میدهد، بلکه گراف وابستگیها را تمیزتر و فرآیند Restore را سریعتر و قابل اعتمادتر میکند.
هرس بستهها چیست؟
Package Pruning فرآیندی است که در زمان Restore توسط NuGet انجام میشود. اگر بستهای قبلاً توسط کتابخانههای زمان اجرای NET (NET Runtime Libraries). ارائه شده باشد، NuGet آن را از گراف وابستگی حذف میکند. .NET SDK لیستی از بستههای فراهمشده توسط هر Target Framework همراه با بالاترین نسخه موجود را نگهداری میکند. اگر وابستگی گذرایی در محدوده نسخههای ارائهشده توسط فریمورک باشد، هرس میشود.
نکته مهم:
- بستههای گذرا (Transitive) که هرس شوند، کاملاً از گراف حذف میشوند؛ دانلود نمیشوند، در خروجی Restore ظاهر نمیشوند و در گزارشهای Audit هم نشان داده نمیشوند.
- بستههای مستقیم (Direct) که هرسپذیر هستند، به صورت خودکار با
PrivateAssets="all" و IncludeAssets="none" مدیریت میشوند تا در فایل nuspec منتشرشده جریان پیدا نکنند. NuGet در این حالت هشدار NU1510 صادر میکند تا توسعهدهنده بتواند آن PackageReference را کاملاً حذف کند.
قبل و بعد از هرس بستهها
فرض کنید پروژهای با Target Framework net10.0 به بستههای Microsoft.Extensions.AI و NuGet.Protocol وابسته باشد.
بدون هرس: گراف Restore شامل بستههایی مانند System.Formats.Asn1 6.0.0، System.Text.Json، System.Diagnostics.DiagnosticSource و غیره میشود. حتی اگر Runtime .NET 10 نسخه جدیدتر و امنتری از این بستهها را داشته باشد، NuGet Audit ممکن است هشدار آسیبپذیری (مانند NU1903) صادر کند.
با هرس (در .NET 10): بستههای فراهمشده توسط Runtime مانند System.Formats.Asn1، System.Text.Json، System.Threading.Channels و System.Diagnostics.DiagnosticSource از گراف حذف میشوند. نتیجه: حذف هشدارهای مثبت کاذب و گراف بسیار سبکتر.
این تغییر بهویژه در پروژههایی با درخت وابستگی عمیق، کاهش چشمگیری (گاهی تا ۷۰٪) در گزارشهای آسیبپذیری گذرا ایجاد میکند.
تغییرات کلیدی در .NET 10
- فعالسازی پیشفرض: ویژگی Package Pruning از .NET 9 به صورت اختیاری وجود داشت، اما در .NET 10 به صورت پیشفرض فعال است.
- رفتار در پروژههای Multi-Target: اگر حتی یکی از Target Frameworkها
net10.0 یا بالاتر باشد، هرس برای تمام فریمورکهای پروژه اعمال میشود. - همافزایی با NuGetAuditMode: مقدار پیشفرض
NuGetAuditMode به all تغییر کرده است. یعنی NuGet اکنون بهطور پیشفرض وابستگیهای گذرا را هم هرس میکند. ترکیب این دو ویژگی باعث میشود گزارشهای Audit واقعاً actionable (قابل اقدام) باشند.
تنظیمات پیشفرض .NET 10 به این شکل است:
<PropertyGroup>
<NuGetAuditMode>all</NuGetAuditMode>
<RestoreEnablePackagePruning>true</RestoreEnablePackagePruning>
</PropertyGroup>
مزایای عملی
علاوه بر کاهش چشمگیر گزارشهای مثبت کاذب، هرس بستهها مزایای دیگری نیز دارد:
- گراف وابستگی سبکتر: تعداد بستههای کمتری باید resolve شوند که منجر به کاهش تعارض نسخه و افزایش احتمال موفقیت Restore میشود.
- سرعت بالاتر: طبق telemetry مایکروسافت، در برخی پروژهها زمان Restore تا ۵۰٪ کاهش یافته است.
- وضوح بیشتر: وابستگیهای واقعی پروژه شفافتر میشوند و توسعهدهنده دقیقاً میداند کدام بستهها واقعاً خارج از Runtime استفاده میشوند.
- نگهداری بهتر: با گذشت زمان و ادغام بستههای بیشتر در Runtime، هرس بهطور خودکار گراف را بهروز و تمیز نگه میدارد.
نتیجهگیری
ویژگی Package Pruning در .NET 10 نشاندهنده تکامل مهم اکوسیستم NuGet است. این ویژگی گراف وابستگی را به چیزی که برنامه واقعاً استفاده میکند نزدیکتر میکند، گزارشهای آسیبپذیری را معنادارتر کرده و تجربه توسعه را حرفهایتر و کمدردسرتر میسازد. توصیه میشود توسعهدهندگان پروژههای موجود خود را به .NET 10 ارتقا دهند و از تنظیمات پیشفرض جدید استفاده کنند. همچنین بررسی دورهای وابستگیهای مستقیم و حذف مواردی که NuGet با هشدار NU1510 پیشنهاد میدهد، بهترین روش برای بهرهبرداری کامل از این قابلیت است. با این تغییرات، مدیریت وابستگیها در .NET بیش از پیش به سمت «کمتر اما دقیقتر» حرکت کرده است؛ فلسفهای که هر توسعهدهندهای از آن استقبال خواهد کرد.