3 puan yazan GN⁺ 2025-12-19 | 1 yorum | WhatsApp'ta paylaş
  • Seattle Times, Shai-Hulud 2.0 saldırısından tesadüfen kurtuldu; ancak şansın bir güvenlik stratejisi olamayacağı varsayımıyla istemci tarafı savunmaları devreye aldı
  • npm’deki Trusted publishing / provenance / ayrıntılı tokenlar gibi iyileştirmeler “yayınlama” tarafını güçlendiriyor, ancak “kurulum·güncelleme” anındaki kötü amaçlı kod çalıştırılmasını engelleyemeyen bir boşluk bırakıyor
  • pnpm, npm kayıt defterini aynen kullanırken tüketim (install/update) aşamasında kötü amaçlı paketlerin çalıştırılmasını zorlaştıran denetimler ekleyen bir yapıya sahip
  • Pilot uygulamada pnpm’in 3 denetimi uygulanarak lifecycle script çalıştırma, en son sürümün anında kurulması, güven seviyesinin düşürülmesi gibi vektörlerin her birini engelleyecek şekilde tasarlandı
  • İstisnalar bir başarısızlık değil, tasarımın bir parçası olarak görülüyor; istisnalar belgelenirken diğer katmanların korumaya devam ettiği bir defense-in-depth işletimi hedefleniyor

Olayın arka planı ve varsayımlar

  • 2025 Kasım’ında kendi kendini kopyalayan bir npm solucanı 796 paketi enfekte etti ve aylık 132 milyon indirme ölçeğinde yayıldı
  • Saldırı, preinstall scriptini kullanarak kimlik bilgisi hırsızlığına, kalıcı arka kapı kurulumuna ve bazı ortamlarda geliştirme ortamının silinmesine kadar vardı
  • Kuruluşumuzun etkilenmemesinin nedeni güçlü savunmalar değil, saldırı süresince npm install/npm update çalıştırılmamış olması gibi bir tesadüftü
  • Haber kuruluşlarında güven esastır; tedarik zinciri ihlali müşteri verilerini, çalışan kimlik bilgilerini, production altyapısını ve kaynak kodunu açığa çıkarabilir, ayrıca kurtarma ve bildirim maliyetleri yüksektir

Ekip ve benimseme bağlamı

  • Seattle Times uzun süredir varsayılan paket yöneticisi olarak npm kullanıyordu; Yarn denemeleri oldu ancak kalıcı hale gelmedi
  • pnpm’in benimsenme nedeni, kayıt defteri düzeyindeki iyileştirmeleri tamamlayan istemci tarafı güvenlik denetimleri sunması
  • pnpm, aynı kayıt defteri·aynı komutlar·aynı iş akışıyla çalışan bir drop-in replacement olduğu için geçiş olasılığı yüksek görüldü
  • Bu, tamamlanmış bir vaka çalışması değil; gerçek bir ekibin tedarik zinciri güvenliğine yeni başlarken yaşadığı sorunları ve düşünce sürecini paylaşmasıdır

Neden istemci tarafı denetimler gerekli

  • npm’in güvenlik iyileştirmeleriyle hesap ele geçirildikten sonra kötü amaçlı paket yayınlamak daha zor hale geldi
  • Bu iyileştirmeler “yayınlama (publishing)” tarafını koruyor, ancak “tüketim (consuming)” aşamasında kötü amaçlı paketin kurulmasını bizzat engellemiyor
  • npm install/npm update sırasında lifecycle scripts (preinstall/postinstall vb.), paket güvenliği değerlendirilmeden önce geliştirici yetkileriyle rastgele kod çalıştırabiliyor
  • Bu scriptler npm/GitHub/AWS/DB kimlik bilgilerine, kaynak koda, bulut altyapısına ve tüm dosya sistemine erişebiliyor
  • Shai-Hulud benzeri saldırılar bu yapıyı kötüye kullanıyor; bakım sorumlusu hesabı ele geçirilirse kötü amaçlı script kurulum anında çalışıyor ve topluluk fark etmeden önce zarar oluşabiliyor
  • npm’in yayınlama tarafı iyileştirmeleri + pnpm’in tüketim tarafı denetimleri, birbirini tamamlayan savunmalar olarak birleştirilip “defense-in-depth” şeklinde kurgulanıyor

Uygulanan 3 katman

  • Pilotta farklı saldırı vektörlerini hedefleyen 3 denetim birlikte kullanıldı
  • Her denetim, gerçekçi istisnalar için bir çıkış yolu içeriyor; tasarım baştan itibaren gerçek ortamda istisnaların gerekeceği kabulüyle yapıldı

Denetim 1: Lifecycle Script Yönetimi

  • pnpm varsayılan olarak lifecycle scriptlerini engelleyebilir ve kurulum uyarıyla devam edebilir
  • Uyarıların göz ardı edilebileceği kaygısıyla strictDepBuilds: true seçildi; böylece script varsa kurulum anında başarısız olacak şekilde zorlandı
  • Yapılandırma örneği pnpm-workspace.yaml içinde şu alanlardan oluşuyor
    • strictDepBuilds: true
    • onlyBuiltDependencies: gerekli build scriptlerine sahip paketler için izin listesi
    • ignoredBuiltDependencies: gereksiz build scriptlerine sahip paketler için engelleme (veya yok sayma) listesi
  • “Gerekli scriptler”, native eklenti derleme veya platforma bağımlı kütüphaneleri bağlama gibi işlemler olarak tanımlandı
  • “Gereksiz scriptler” ise optimizasyon ya da isteğe bağlı ayar niteliğinde olup, ekibin kullanım biçiminde işlevi etkilemeyen durumlar olarak tanımlandı
  • Kurulumun başarısız olması şu sonraki adımları zorunlu kılıyor
    • pnpm, hangi pakette script olduğunu açıkça gösteriyor
    • Script davranışı araştırılıp anlaşılıyor
    • İzin/verme veya engelleme kararı insan değerlendirmesiyle bilinçli olarak alınıp belgeleniyor
  • pnpm ekibi, v11’de strictDepBuilds: true seçeneğini varsayılan yapmayı değerlendiriyor ve allow/deny söz dizimi adlarını iyileştirmeyi de inceliyor

Denetim 2: Sürüm Bekleme Süresi

  • Yakın zamanda yayımlanmış sürümlerin kurulumu belirli bir bekleme süresi boyunca engellenerek, topluluğa kötü amaçlı paketleri tespit edip kaldırması için zaman tanınıyor
  • Yapılandırma örneği pnpm-workspace.yaml içinde şu alanlardan oluşuyor
    • minimumReleaseAge: <duration-in-minutes>
    • minimumReleaseAgeExclude: acil hotfix gibi istisnalar için izin listesi
  • “En yeni en iyidir” alışkanlığından vazgeçip, tedarik zinciri perspektifinde biraz daha eski olanın daha güvenli olabileceği düşüncesine geçmek gerekiyor
  • Eylül 2025 saldırısında (debug, chalk dahil 16 paket) kaldırma yaklaşık 2,5 saat sürdü; Kasım 2025’teki Shai-Hulud 2.0’da ise yaklaşık 12 saat gerekti
  • Kuruluşun risk toleransına göre bekleme süresi saat/gün/hafta olabilir; hangi biçimde olursa olsun bu saldırıyı engellemiş olurdu
  • Kuruluşun zaten her zaman en son sürümü kullanamaması gerçeğiyle iyi örtüşüyor; bu yüzden bekleme süresi işi ciddi biçimde aksatmıyor
  • Güvenlik yaması veya kritik hata gibi gerçekten gerekli durumlarda inceleme sonrası istisna verilebilir

Denetim 3: Güven Politikası

  • Önceki sürümden daha zayıf kimlik doğrulamayla yayımlanmış bir sürüm ortaya çıkarsa kurulumu engelliyor
  • Bunun, bakım sorumlusu hesabı ele geçirilip resmi CI/CD yerine saldırganın makinesinden yayın yapıldığına dair bir sinyal olduğu açıklanıyor
  • Yapılandırma örneği pnpm-workspace.yaml içinde şu alanlardan oluşuyor
    • trustPolicy: no-downgrade
    • trustPolicyExclude: CI/CD geçişi gibi istisnalar için izin listesi
  • npm’in paket yayını için 3 aşamalı bir güven seviyesi izlediği anlatılıyor (güçlü→zayıf)
    • Trusted Publisher: GitHub Actions + OIDC + npm provenance tabanlı
    • Provenance: CI/CD’de imzalı attestation
    • No Trust Evidence: kullanıcı adı/şifre veya token tabanlı yayın
  • Yeni sürümün güven seviyesi öncekinden düşükse kurulum başarısız oluyor
  • Ağustos 2025’teki s1ngularity saldırısında, saldırganın CI/CD erişimi olmadan yerelden kötü amaçlı sürüm yayınladığı ve provenance bulunmadığı olayda bu denetim kurulumu engellemiş olurdu
  • Meşru düşüş örnekleri olarak yeni bir bakım sorumlusunun katılması, CI/CD geçişi veya CI/CD arızası sırasında manuel hotfix veriliyor; inceleme sonrası istisna listesine ekleniyor
  • Bu özelliğin, 2025 Kasım’ında pnpm’e eklenen yeni bir özellik olduğu ve meşru düşüşlerin pratikte ne kadar sık yaşanacağının hâlâ öğrenildiği belirtiliyor

Katman birleşiminin çalışma örneği: React güvenlik açığı yaması

  • 2025 Aralık’ta duyurulan React Server Components içindeki kritik güvenlik açığı yamasının hemen uygulanması gereken senaryoda
  • Normalde bekleme süresi “az önce yayımlanmış sürümün kurulmasını” engeller, ancak kritik bir güvenlik yamasında beklemek mümkün değildir
  • Bu durumda minimumReleaseAgeExclude içine belirli React sürümü eklenir; ancak istisna, güvenlik duyurusu ve yamanın meşruiyeti incelendikten sonra uygulanır
  • İstisna uygulansa bile diğer katmanlar korumaya devam eder
    • React’te genellikle lifecycle script yoktur; bu yüzden yama sürümünde script ortaya çıkarsa hemen şüphe sinyali olur ve engellenebilir
    • Saldırgan kimlik bilgilerini ele geçirip yerelden bir “yama” yayımlarsa güven seviyesindeki düşüş nedeniyle engellenebilir
  • İstisna, “güvenlik başarısızlığı” olarak değil; bir katman aşılmış olsa da diğer katmanların kaldığı ve tek hata noktasını ortadan kaldıran bir tasarım olarak görülüyor

Pilot uygulama sonuçları

  • Tek bir backend servisine 3 denetimin tamamı uygulanarak PoC yapıldı
  • Araştırma, anlama ve yaklaşımı tanımlama dahil toplam hazırlık süresi birkaç saat düzeyindeydi
  • pnpm, lifecycle script içeren 3 paket tespit etti
    • esbuild: CLI başlangıcını milisaniye düzeyinde optimize ediyor, ancak ekip yalnızca JS API kullandığı için gereksiz görüldü
    • @firebase/util: istemci SDK’sını otomatik yapılandırıyor, ancak ekip yalnızca sunucu SDK’sını kullandığı için gereksiz görüldü
    • protobufjs: şema uyumluluğu kontrolü yapıyor, ancak yalnızca transitif bağımlılık olarak kullanıldığı ve ekibin kullanım senaryosunda gereksiz olduğu değerlendirildi
  • Dokümantasyon incelemesi ve script analizi (script yorumlamada yapay zeka desteği dahil) sonrasında, üç scriptin de ekibin kullanım senaryosu için gerekli olmadığı sonucuna varılıp engellendi
  • İşlevsel bir etki olmadı
  • Sürtünme (friction), ortamda çalışan koda örtük olarak güvenilmemesini sağlayan kasıtlı bir zorlayıcı mekanizma olarak değerlendiriliyor
  • Yeni bir bağımlılıkta script varsa, inceleme ve belgelemenin yaklaşık 15 dakika süreceği tahmin ediliyor

Operasyon sırasında edinilen dersler

  • İstemci tarafı katmanlar + npm’in yayınlama tarafı iyileştirmeleri birleştiğinde defense-in-depth’in gerçekten işe yaradığı hissedildi
  • İstisna uygulansa bile diğer katmanların kalması, istisnalarla ilgili kaygıyı azaltıyor
  • Önce kolaylık yaklaşımından önce güvenlik yaklaşımına geçişte zihinsel modelin değişmesi zaman alıyor; ancak alışınca doğal geliyor
  • Ayrı bir güvenlik ekibi olmayan orta ölçekli kuruluşlarda da pratik biçimde uygulanabilir
  • Trust policy, kullanıma alınalı sadece birkaç hafta olmuş bir özellik; bu nedenle meşru güven düşüşlerinin sıklığı ve operasyonel hissiyat daha fazla öğrenilmeli
  • Yakın dönemde başka kod tabanlarına da genişletilmesi planlanıyor; farklı bağımlılık grafiğine sahip uygulamalardan daha fazla veri toplanacak

Diğer ekipler için uygulama ipuçları

  • Önce tek bir projede başlayıp iş akışını ve sürtünme noktalarını öğrenmek öneriliyor
  • Lifecycle scriptler, sürüm bekleme süresi ve güven düşüşü senaryolarının tümünde istisna gerekebileceğinden, baştan itibaren istisnaları varsayarak tasarlayın
  • Uyarı tabanlı yaklaşım yerine, kurulumu başarısızlığa zorlayan strictDepBuilds: true seçeneğinin ilk günden kullanılması tavsiye ediliyor
  • Tüm istisnaları belgeleyerek denetim izi bırakın ve ileride temizlemeyi kolaylaştırın
  • Bir katmandaki istisnanın, diğer katmanların korumasını ortadan kaldırmadığını aklınızda tutun

1 yorum

 
bichi 2025-12-19

pnpm! pnpm! pnpm! Yine de güvenilir olduğunu düşünüyorum