.NET Projende Gizli Paketleri Bulma: dotnet nuget why Kullanım Rehberi

CI/CD pipeline’ında Trivy, Snyk veya benzeri bir güvenlik tarama aracı çalıştırdığında bazen karşına hiç tanımadığın bir paket ismi çıkar. Örneğin geçtiğimiz hafta bir taramada şöyle bir uyarı gördüm:

HIGH — CVE-2026-48109 — MessagePack — LZ4 decompression sırasında bellek referans hatası riski.

Projenin .csproj dosyasında MessagePack diye bir referans yoktu. İlk refleks “tarama aracı yanlış paket gösteriyor” olabilir ama aslında durum şu: paket gerçekten imajın içinde, sadece doğrudan değil transitive (dolaylı) bağımlılık olarak geliyor — kullandığın başka bir NuGet paketi (Redis client, SignalR entegrasyonu, Orleans, Dapr.Client gibi) onu kendi içinde çekiyor.

Bu makalenin konusu tam olarak bu: bir paket projende doğrudan görünmüyorsa, onu projene gerçekten kimin çektiğini nasıl buluruz? Cevap: dotnet nuget why.

dotnet nuget why Nedir?

dotnet nuget why, .NET 8 SDK 8.0.4xx ve sonrasıyla gelen bir CLI komutu. Belirttiğin paketin proje (veya solution) içindeki tam bağımlılık zincirini ağaç halinde gösterir — yani “bu paket bana nereden, hangi paket üzerinden geliyor?” sorusunun doğrudan cevabı.

Bundan önce bu işi yapmak için dotnet list package --include-transitive çalıştırıp çıkan uzun listede paketi bulmak, sonra elle hangi üst paketin onu çektiğini tahmin etmeye çalışmak gerekiyordu. dotnet nuget why bu manuel işi tamamen ortadan kaldırıyor.

Ön Koşullar

  • .NET SDK 8.0.4xx veya üzeri (kontrol için dotnet --version)
  • Proje en az bir kez restore edilmiş olmalı (dotnet restore), çünkü komut obj/project.assets.json dosyasındaki dependency graph’ı okuyor

Temel Kullanım

dotnet nuget why <proje_veya_solution_yolu> <paket_adi>

Örnek:

dotnet nuget why ./src/MyService/MyService.csproj MessagePack

Çıktı şöyle bir şey verir:

Project 'MyService' has the following dependency graph(s) for 'MessagePack':

[net8.0]
 └─ StackExchange.Redis.Extensions.MsgPack (2.6.0)
     └─ MessagePack (2.4.59)

Bu çıktıyı okumak çok basit: en alttaki paket (MessagePack) projeye StackExchange.Redis.Extensions.MsgPack üzerinden, o da senin projenin doğrudan bağımlılığı olduğu için geliyor. Zincir uzunsa (3-4 katman) komut tüm katmanları sırayla gösterir.

Solution Genelinde Arama

Komutu tek bir .csproj yerine .sln dosyasına da verebilirsin; bu durumda solution içindeki her projede ilgili paketin nereden geldiğini tek seferde görürsün:

dotnet nuget why MyProject.sln MessagePack

Bu özellikle mikroservis mimarisinde, aynı paketin birden fazla projeye farklı yollardan sızıp sızmadığını kontrol etmek için kullanışlı.

Birden Fazla Target Framework Varsa

Proje net8.0 ve net48 gibi birden fazla framework’ü hedefliyorsa, çıktı her framework için ayrı bir bağımlılık ağacı gösterir:

[net8.0]
 └─ PackageA (1.2.0)
     └─ MessagePack (2.4.59)

[net48]
 └─ PackageB (3.0.1)
     └─ MessagePack (2.4.59)

Bu, bazı durumlarda paketin sadece tek bir framework için geldiğini, diğerinde hiç bulunmadığını görmeni sağlar — özellikle legacy framework desteği olan projelerde önemli bir detay.

Komut Çalışmazsa veya Daha Fazla Detay Gerekirse

dotnet nuget why SDK sürüm kısıtı nedeniyle her ortamda bulunmayabilir. Bu durumda alternatif yollar:

project.assets.json üzerinden manuel sorgu (jq ile):

jq '.targets["net8.0"] | to_entries[] | select(.value.dependencies."MessagePack") | .key' obj/project.assets.json

Bu, MessagePack’e bağımlı olan tüm üst paketleri listeler.

Visual Studio üzerinden görsel kontrol:

Projeye sağ tık → Manage NuGet PackagesInstalled sekmesinde paketin üstüne tıklayınca alt panelde Dependents listesi çıkar.

dotnet-depends (community tool):

dotnet tool install -g dotnet-depends
dotnet depends

Bu araç tüm bağımlılık ağacını terminal içinde interaktif bir ağaç görünümünde sunar, büyük projelerde gezinmek için dotnet nuget why‘dan daha rahat olabilir.

Kaynağı Bulduktan Sonra Ne Yapmalı?

Zinciri gördükten sonra elindeki seçenekler:

  1. Üst paketi güncelle — eğer üst paket (örnekteki StackExchange.Redis.Extensions.MsgPack) zaten daha yeni bir MessagePack sürümüyle çalışan bir versiyona güncellendiyse, sadece onu yükseltmek yeterli.
  2. Alt paketi doğrudan pinle — üst paket güncellenmemişse, kendi .csproj‘una doğrudan bir PackageReference ekleyerek transitive sürümün üzerine yazabilirsin:
<PackageReference Include="MessagePack" Version="2.5.301" />

NuGet, aynı paket için birden fazla sürüm talebi olduğunda her zaman en yüksek pinlenen sürümü seçer, dolayısıyla bu yöntem güvenle çalışır.

Çok Repolu Ortamlarda Pratik Not

10’larca mikroservis reposu yönetiyorsan, dotnet nuget why komutunu bir script içinde tüm repoları gezecek şekilde otomatikleştirmek işini hızlandırır:

for sln in $(find . -name "*.sln"); do
  echo "=== $sln ==="
  dotnet nuget why "$sln" MessagePack 2>/dev/null
done

Bu şekilde, aynı paketin hangi repolara hangi üst paket üzerinden sızdığını tek komutla görebilirsin. Tekrarlayan bu tür sorunlarla sık karşılaşıyorsan, sürüm yönetimini merkezi bir Directory.Packages.props dosyasına taşımak da uzun vadede aynı paketin farklı repolarda farklı sürümlerde dolaşmasını önler.

Özet: Bir güvenlik taraması veya bağımlılık listesi sana tanımadığın bir paket gösterdiğinde, onu projene kimin çektiğini anlamanın en hızlı yolu dotnet nuget why <proje/sln> <paket> komutu. Komut yoksa project.assets.json + jq, Visual Studio’nun Dependents paneli veya dotnet-depends aracı aynı bilgiyi farklı şekillerde verir.

Bunlar da hoşunuza gidebilir...