3 puan yazan GN⁺ 2025-09-20 | 1 yorum | WhatsApp'ta paylaş
  • Açık kaynak paketi @ctrl/tinycolor'ı içeren çok sayıda npm paketi kötü amaçlı sürümlerle enfekte oldu; bunun nedeni, ortak kullanılan bir depodaki GitHub Actions workflow'u üzerinden npm token'ının çalınmasıydı
  • Saldırgan, geniş yetkilere sahip npm token'ını kullanarak yaklaşık 20 pakete kötü amaçlı kod dağıttı; bunlar arasında @ctrl/tinycolor haftalık 2 milyon indirmeye ulaştığı için etkisi büyüktü
  • Enfekte sürümler postinstall aşamasında kötü amaçlı payload çalıştırdı; GitHub ve npm güvenlik ekipleri hızla müdahale ederek kaldırma ve temizlik işlemlerini gerçekleştirdi
  • Yazar, tekrarını önlemek için Trusted Publishing (OIDC) geçişi, token yetkilerinin en aza indirilmesi, 2FA zorunluluğu ve pnpm özelliklerinden yararlanılması gibi güçlendirilmiş bir güvenlik planı hazırladı
  • Bu olay, yazılım tedarik zinciri güvenliğinin kırılganlığını gösteriyor ve npm ekosistemi genelinde güvenlik özelliklerinin iyileştirilmesiyle güvenlik pratiklerinin değişmesi gerektiğini ortaya koyuyor

TL;DR

  • Kötü amaçlı bir GitHub Actions workflow'u paylaşılan bir depoya push edilerek npm token'ı çalındı
  • Bu token ile saldırgan 20 paketin kötü amaçlı sürümlerini yayımladı; bunlar arasında @ctrl/tinycolor yüksek indirme sayısı nedeniyle daha büyük etki yarattı
  • Kişisel hesaplar veya repolar doğrudan ele geçirilmedi; ayrıca phishing ya da yerel kötü amaçlı yazılım kurulumu da olmadı
  • GitHub/npm güvenlik ekiplerinin hızlı müdahalesiyle kötü amaçlı sürümler kaldırıldı, ardından cache'i temizlemek için temiz sürümler yeniden yayımlandı

Olay nasıl fark edildi? (How I Found Out)

  • 15 Eylül öğleden sonra topluluk üyesi Wes Todd, Bluesky DM üzerinden sorunu bildirdi
  • GitHub/npm güvenlik ekipleri etkilenen paketlerin listesini çoktan toparlamış ve kaldırma sürecini başlatmıştı
  • İlk ipucu olarak paylaşılan kötü amaçlı branch adı 'Shai-Hulud'du; bu ad Dune evrenindeki kumsolucanından geliyor

Gerçekte ne oldu? (What Actually Happened)

  • Uzun zaman önce birlikte çalışılan angulartics2 deposunda, hâlâ admin yetkisine sahip bir işbirlikçi bulunuyordu
  • Bu depoda saklanan npm token'ı, kötü amaçlı bir GitHub Actions workflow'u tarafından çalındı
  • Saldırgan bu token ile @ctrl/tinycolor dahil yaklaşık 20 paketi yayımladı
  • GitHub/npm güvenlik ekipleri kötü amaçlı sürümleri hızla kaldırdı ve yazar güvenilir yeni sürümleri tekrar yayımladı
Reklam

Etki (Impact)

  • Kötü amaçlı sürümler kurulduğunda postinstall script'i çalışarak güvenlik tehdidi oluşturdu
  • Etkilenen kullanıcıların StepSecurity'nin anlık müdahale rehberine başvurması öneriliyor

Yayınlama ortamı ve müdahale planı (Publishing Setup & Interim Plan)

  • Daha önce otomatik yayınlama için semantic-release + GitHub Actions kombinasyonu kullanılıyordu
  • npm'nin provenance özelliği kullanılmış olsa da, geçerli bir token'a sahip saldırganı engelleyemedi
  • İleride statik token'ları kaldırmak için Trusted Publishing (OIDC) kullanılacak
  • Şu anda tüm token'lar iptal edildi; ayrıca 2FA zorunlu hale getirildi, yalnızca granular yetkili token'lara izin veriliyor ve pnpm'in minimumReleaseAge özelliği gibi ek güvenlik önlemleri değerlendiriliyor

İdeal iyileştirmeler (Publishing Wishlist)

  • npm hesap düzeyinde OIDC tabanlı Trusted Publishing'i zorlama seçeneği sunulmalı
  • provenance eksik olduğunda yayını engelleme özelliği ile semantic-release ve OIDC'nin tam entegrasyonu sağlanmalı
  • GitHub arayüzünde 2FA tabanlı manuel onaylı yayınlama özelliği sunulması isteniyor
  • Pro abonelik olmadan da GitHub Environments düzeyindeki koruma özellikleri kullanılabilmeli
  • npm paket sayfalarında postinstall script'i bulunup bulunmadığı gösterilmeli ve silinen sürümlerin neden kaldırıldığı açıklanmalı

1 yorum

 
GN⁺ 2025-09-20
Hacker News görüşleri
  • Söz konusu depoda hâlâ GitHub Actions secret’ları, yani geniş kapsamlı yayınlama yetkisine sahip npm token’ları duruyordu
    Trusted Publishing’in avantajlarından biri, artık uzun süre geçerli yayınlama token’ları kullanmak zorunda olmamanızdır
    Artık yalnızca CI VM üzerinde kısa süreli oluşturulan token’lar kullanılıyor ve bu token’lar sadece 15 dakika geçerli
    Bu yaklaşım zaten PyPI, npm, Cargo, Homebrew gibi birçok ekosistemde uygulanıyor
    Yayın süreci aslında biraz daha kolaylaştığı için herkesin denemesini tavsiye ederim
    Belgeler hâlâ belirsiz geliyorsa her zaman yardım isteyebilirsiniz
    Ekosistem yöneticileri de bu özelliğin yaygınlaşmasını açıkça istiyor
    Trusted Publishing resmi belgeleri

    • npm’de artık Trusted Publishing kullanılabildiğini bunu vesileyle ilk kez öğrenmiş oldum
      İlgili duyuru
      Bu hafta sonu hemen kurmayı planlıyorum

    • Artık bunun gibi özellikleri kullanan projeleri depoda gösteren bir işaret olsa iyi olurdu
      Böylece bunu kullanmayan bağımlılık paketlerini kolayca engelleyebilirdik

  • Otomatik dağıtım sürecine MFA’nın (çok faktörlü kimlik doğrulama) dahil edilmesi konusu yeterince dikkat çekmiyor gibi geliyor
    CI workflow ile yayın yapıp MFA istemiyle yayını onaylamak sorun değil, ama en son baktığımda bunun için kod sağlamak amacıyla bir HTTPS tüneli açmak gerekiyordu ve bu da işleri karmaşıklaştırıyordu
    npm ya da GitHub’ın CI sırasında MFA kodunu kolayca sağlama ve onaylama yolunu doğrudan sunmasını isterdim

    • Paket yayınlamanın 2 aşaması var: paketi npmjs’e yükleme aşaması ve onu gerçekten kullanıcılara açma aşaması
      Şu anda bu ikisi tek bir işlem içinde birleşmiş durumda
      Bence bunları ayırmak daha doğru olur; CI sistemi otomatik olarak sadece build alıp yükleme yapsın
      Yüklenen paketin gerçekten dağıtıma çıkması içinse bir insanın npmjs sitesine doğrudan giriş yapıp elle publish etmesi ve MFA’dan geçmesi gerekir

    • Aslında paket publish etmenin kendisi gereksiz bir kavram olabilir mi diye düşünüyorum
      Eğer VCS “gerçek kaynak” ise, ayrı bir yayınlama süreci olmadan doğrudan kullanılabilmeli
      Go dili gerçekten bunu yapıyor
      Paketleri doğrudan URL tabanlı import ediyor ve sürümlemeyi tag’lerle yönetiyor
      Böylece yalnızca VCS’ye güvenmek yeterli oluyor ve ek saldırı yüzeyi azalıyor
      Ayrı arşiv dosyalarını diff etmek yerine sadece commit düzeyinde inceleme yapmak yeterli
      Sorun, depo taşındığında import yolunun değişmesi; ama bu da bir bakıma avantaj sayılabilir
      Bunun dışında ayrı bir yayınlama aşamasının ne fayda sağladığını pek bilmiyorum
      Sanki eski FTP ile tar arşivi yüklenen dönemlerden kalma bir kalıntı gibi

  • Daha önce angulartics2 adlı paylaşımlı bir depoda çalışmıştım
    Orada hâlâ geniş yayınlama yetkisine sahip npm token’ı içeren GitHub Actions secret’ları vardı
    İş birliği yaptığımız kişilerden birinin birden çok projede yetkisi vardı ve birden fazla paketin aynı anda etkilenmesinin nedeni de muhtemelen buydu
    Shai-Hulud adlı yeni bir branch, kötü amaçlı github action workflow ile birlikte force push edildi
    Yönetici yetkisine sahip bir contributor olduğu için inceleme gerekmeksizin workflow hemen çalıştı ve npm token’ı sızdırıldı
    Sızdırılan token ile 20 pakete kötü amaçlı sürümler dağıtıldı
    Bunların çoğu yaygın kullanılmayan paketlerdi ama @ctrl/tinycolor haftada yaklaşık 2 milyon kez indirilen popüler bir paket
    Hâlâ anlamadığım şey, angulartics2 deposundaki npm token’ı ile tinycolor’a nasıl publish yapılabildiği

    • Benim de başka birinin npm deposunda yönetici yetkim var ve son sürümlerin çoğunu da neredeyse ben çıkardım
      Yönetici olduktan sonra, uzun süredir birikmiş sorunları bu vesileyle düzeltmek istediğim için commit’lerin çoğu da benim adıma görünmeye başladı
      GitHub action ile paket publish etme fikrine neredeyse ikna olmuştum, ama 2FA ile elle dağıtım yaparken yanlışlıkla master dışı bir durumu publish etmekten hep korkuyordum
      Bu yüzden diğer yöneticilerle bunu konuşmayı da ertelemiştim; sonunda böyle bir şey yaşanınca ertelemekte haklıymışım gibi hissediyorum
      Doğru cevabın ne olduğunu bilmiyorum ama kimlik bilgilerini üçüncü taraflara emanet etmek kesinlikle iyi bir çözüm gibi durmuyor

    • angulartics2’nin npm token’ı neden tinycolor dağıtım yetkisine sahip olsun ki?
      Bu gerçekten klasik bir organizasyon hack yolu gibi
      Geçmişte bırakılmış “eski günahlar” bir gün geri dönüp vuruyor
      Birkaç yıl önce bizim organizasyonda da buna benzer bir şey olmuştu
      Üç kez değiştirilmiş eski bir editörde kalan güvenlik açığı yüzünden sunucuya yükleme yapılmasına izin verilebilmişti
      Bunu build zamanında bulmadık, sonunda URL taramasıyla keşfettik

    • Yeterince açık anlatmadıysam kusura bakmayın
      Bu token, benim tüm npm paketlerim üzerinde global publish yetkisine sahip bir token’dı

  • Son 10 yıldır manuel release savunuyorum
    Her zaman çok itiraz geldi ama artık o kadar da garip bir fikir gibi görünmüyor
    CI/CD’nin havalı olduğunu biliyorum ama bu olay ya da son dönemdeki CF meseleleri, otomasyon yüzünden ciddi sorunların daha kolay ortaya çıkabildiğine dair giderek daha fazla kanıt sunuyor
    Bir zamanlar BigBank’te çalışırken production dağıtımı için en az beş kişi hazır bekler, pek çok prosedür uygulanırdı; ama en azından neyin dağıtıldığını kesin olarak biliyorduk

    • Kesinlikle katılıyorum
      Bence GitHub Actions ya da otomatik release script’leri yerine, eskisi gibi elle build alıp imzalayıp tarball yükleyip doğrulamak çok daha güvenli
      Dağıtım sistemleri (örneğin Debian gibi distribution paketleme sistemleri) ayrıca bir doğrulama aşamasından da geçiyor; xz olayında tüm internetin ele geçirilmemesinin nedenlerinden biri de buydu
      En azından release publish edilmeden önce bir insanın binary’yi bizzat imzalamasını zorunlu kılmak gerekir
      Saldırganın kendini maintainer olarak ekleyip kendi anahtarıyla imzalaması da mümkün olduğundan, distribution paketleme sistemlerindeki gibi güvenilir anahtar yönetimi de eşlik etmeli ki daha güvenli olsun
      Eğer tehdit modelim “tek bir GitHub hesabı ya da API anahtarı sızarsa bütün kullanıcı tabanı düşer” varsayımına dayanıyorsa, bunun gerçekten makul olup olmadığını yeniden düşünmem gerekir
  • Yayınlama için 2FA kullanmak iyi ama birden fazla yazarın kriptografik imza ile onay vermesi çok daha güvenli olur
    Tek bir kişinin ele geçirilmesi saldırının başarıya ulaşmasına yetmemeli

    • Birçok paketin yazarı zaten yalnızca bir kişi

    • Birden fazla yazarın imzasını zorunlu kılmak iyi bir fikir, ama commit’lerde, tag’lerde ve çıktı artefact’larında herhangi bir biçimde imza doğrulaması yapılabilse bile saldırıların çoğu önlenebilir
      Distribution paketleme sistemleri imza doğrulamasını çok iyi destekliyor ama dil paket yöneticilerinde bu doğrulama zinciri zayıf
      Örneğin runc’ın resmi release süreci tamamen maintainer anahtarlarıyla imzalanıyor ve anahtarlar Yubikey gibi cihazlarda tutuluyor
      Distribution sistemleri de ayrı keyring’ler yöneterek resmi kaynak ve binary’leri doğruluyor
      Böyle bir süreç olsaydı bu saldırı da muhtemelen birden fazla aşamada engellenirdi
      CI’da doğrudan build alınabilir, ama final aşamada maintainer’ın bizzat imzaladığı bir yapı gerekli
      Dil paket yöneticilerinde böyle bir workflow yoksa Trusted Publishing nispeten daha az kötü bir alternatif sayılabilir
      Ama GitHub hesabı ele geçirilirse (örneğin cookie hırsızlığıyla) anında publish etmek yine mümkün olur
      GitHub, Trusted Publishing için timeout gibi güvenlik ayarları sunuyor ama saldırgan bunları kapatabilir
      Benim hesabım ele geçirilse bile, distribution tarafı benim imzalamadığım bir anahtarla yapılan değişikliği kabul etmeyeceği için nispeten daha güvenli
      Not: SUSE’de çalışıyorum ama openSUSE, Arch ve Gentoo gibi sistemlerde de artefact doğrulama desteğinin artmasını isterim
      İlgili bağlantılar:

    • runc.keyring

    • keyring_validate.sh

    • release_sign.sh

    • openSUSE’nin runc.keyring’i

  • Token’lardan gerçekten nefret ediyorum
    Token dediğiniz şey aslında statik bir paroladan farksız
    Daha düzgün bir kimlik doğrulama yöntemi olması gerektiğini düşünüyorum
    Örneğin GitHub’ı AWS için token sağlayıcısı olarak kullanmak, gördüğüm kadarıyla daha makul bir yöntem
    GitHub-AWS OIDC entegrasyonu
    Ama bu sadece istisnai bir örnek

    • Makineden makineye OIDC akışı doğru uygulanırsa güvenli olabilir, ama kurulumu fazla karmaşık
      Ve sonuçta OIDC de bir bakıma sadece “daha karmaşık bir token” gibi hissettiriyor
      İnsan denetimi olmayan otomasyon ortamlarında her zaman bir yerde sızdırılabilecek bir şey kalıyor; ister token olsun ister token üreteci
      Bu worm örneğinde de OIDC temel çözüm değildi
      GitHub workflow ele geçirilmişse, OIDC olsun olmasın ortama geçici bir kimlik enjekte edilmiş oluyor
      Asıl önemli olan, yetkisiz kullanıcıların secret’lara sahip workflow’ları çalıştıramadığı bir sistem kurmak
      İnce taneli yetki ayrımı isteniyorsa, OIDC yerine belki de token yetki kapsamını daraltmak daha etkili olabilir

    • Token’ın asıl fikri, ömrünün ve yetki kapsamının (authZ) sınırlı olmasıdır
      Ama çoğu durumda pratikte böyle olmuyor ve parola gibi statik şekilde kullanılıyor
      oauth ya da ayrıntılı yetki sınırlaması yapabilen biscuits gibi alternatifler var ama fiilen pek kullanılmıyorlar

    • Trusted Publishing artık npm dâhil çeşitli paket kayıtlarında destekleniyor
      İlgili duyuru

    • Başkalarının da belirttiği gibi, token’lar yalnızca kısa ömürlü olmalı ya da ancak manuel kimlik doğrulamadan (MFA, passphrase vb.) sonra verilmeli

    • mTLS (TLS istemci sertifikası) kullanmak, doğru cevaba daha yakın bir yön gibi görünüyor

  • Güvenlik açığı olan npm paketlerini kontrol etmek için açık bir araç/script bilen var mı?
    stepsecurity sayfasında böyle bir araç yok gibi görünüyor

    • Her şeyi engelleyemez ama provenance-action kullanmak da iyi bir fikir olabilir
      provenance-action

    • Bilinen sorunlar için temel araç npm audit

  • Yerel 2FA tabanlı publish sürdürülebilir değildir
    Yerel 2FA neden sürdürülebilir değil?
    Asıl sorun otomatik publish workflow’u
    Çoğu npm paketi o kadar sık publish edilmiyor ve o kadar karmaşık bir release süreci de gerektirmiyor bence
    Bir insanın doğrudan 2FA ile npm publish yapmasında bu kadar zor olan ne var?
    Bu bile fazla zahmetli geliyorsa, belki de yönetilen paket sayısını yeniden değerlendirmek gerekir

    • Mantıklı bir nokta
      Benim demek istediğim, yerel yayınlamada yanlış branch’ten çıkmak ya da build eksikliği gibi hatalardan biraz endişe duyduğumdu
  • Bir CI job’ın git geçmişinin derin kısımlarına force push ile değişiklik yapması durumunu da düşünmeden edemiyorum

  • Mevcut düzen artık düzgün çalışmıyor
    Elbette OIDC token’ları, zero-trust çözümleri gibi teknik kazanımları övebiliriz
    Ama milyonlarca indirme alan npm kütüphanelerinin bakımcılarının önemli bir kısmı, gerçekten hacklenene ya da npm doğrudan dağıtımı engelleyene kadar güvenliği ciddiye almayacak
    Ve sonra “tüm bağımlılıkları kaldıralım, sadece standart kütüphane kalsın” gibi uygulanamaz öneriler geliyor
    Bağımlılıkları azaltmak iyi bir şey ama mevcut soruna hiçbir çözüm getirmiyor
    Gerçekçi seçenekler ya on binlerce, yüz binlerce kişinin npm’i bırakıp kodlarını baştan yazması, ya da npm’in çok indirilen paketlerden başlayarak 2FA, OIDC gibi kuralları zorunlu kılması ve uymayanların publish etmesini tamamen engellemesi
    Hangi seçeneğin pratikte daha uygulanabilir olduğu çok açık
    Aksi hâlde npm’in itibarı dibe vurur ve ortaya XKCD 927 durumu çıkar