5 puan yazan GN⁺ 2025-09-17 | 1 yorum | WhatsApp'ta paylaş
  • NPM ekosisteminde popüler olan @ctrl/tinycolor dahil 40'tan fazla pakete kendini yayan kötü amaçlı yazılım enjekte edildi; bu da geliştirme ortamlarındaki gizli bilgilerden CI/CD kimlik bilgilerine kadar zincirleme enfeksiyona yol açabilen bir tedarik zinciri saldırısına neden oldu. Enfekte sürümler npm'den kaldırıldı
  • Saldırı yükü, npm kurulum sürecinde Webpack bundle'ını (bundle.js, ~3.6MB) eşzamansız olarak çalıştırıyor ve ortam değişkenleri, dosya sistemi ve bulut SDK'ları üzerinden geniş kapsamlı kimlik bilgisi toplama gerçekleştiriyor
  • Kötü amaçlı mantık, NpmModule.updatePackage ile diğer paketleri zorla yamalayıp yayımlayarak kademeli yayılım sağlıyor; ayrıca GitHub Actions'a shai-hulud workflow'unu enjekte ederek kurumsal secret'ları toJSON(secrets) ile sızdırıyor
  • Toplanan veriler, halka açık GitHub deposu 'Shai-Hulud' oluşturularak dışarı aktarılıyor; süreç meşru geliştirme faaliyetleri gibi gizlendiği için tespit edilmesi zor
  • AWS/GCP/Azure/NPM/GitHub token'larına ve metadata endpoint'lerine erişim ile TruffleHog tabanlı secret taraması gibi teknikler gizlice kullanılıyor
  • Paketlerin derhal kaldırılması, depoların temizlenmesi ve tüm kimlik bilgilerinin değiştirilmesinin yanı sıra CloudTrail/GCP Audit loglarının incelenmesi, webhook'ların engellenmesi, branch protection/Secret Scanning/cooldown politikalarının devreye alınması gerekiyor

Affected Packages

  • Toplam 195 paket/sürüm raporlandı. Öne çıkanlar arasında @ctrl/tinycolor(4.1.1, 4.1.2), çok sayıda @ctrl/ namespace paketi, @crowdstrike/ modül grubu, ngx-bootstrap/ngx-toastr/ng2-file-upload/ngx-color gibi Angular/web UI ekosistemi genelindeki paketler, @nativescript-community/ ve @nstudio/ mobil yığını, teselagen/ yaşam bilimleri araç zinciri, ember-*, koa2-swagger-ui, pm2-gelf-json, wdio-web-reporter yer alıyor
  • Her paket için tam sürümler kaynak tablodan kontrol edilmeli ve bu sürümlerin kullanılıp kullanılmadığı dikkatle çapraz doğrulanmalı
    • Örnek: @ctrl/ngx-emoji-mart 9.2.1, 9.2.2, @ctrl/qbittorrent 9.7.1, 9.7.2, ngx-bootstrap 18.1.4, 19.0.3–20.0.5, ng2-file-upload 7.0.2–9.0.1 gibi geniş bir etki alanı söz konusu

Immediate Actions Required

Identify and Remove Compromised Packages

  • Projede enfekte paketlerin bulunup bulunmadığını kontrol edin: npm ls @ctrl/tinycolor gibi komutlarla inceleyin
  • Enfekte paketleri hemen kaldırın: npm uninstall @ctrl/tinycolor gibi komutları çalıştırın
  • Bilinen bundle.js hash'lerini arayarak yerel izleri kontrol edin: sha256sum | grep 46faab8a... kullanın
Reklam

Clean Infected Repositories

  • kötü amaçlı GitHub Actions workflow'unu silin: .github/workflows/shai-hulud-workflow.yml dosyasını kaldırın
  • Uzakta oluşturulan shai-hulud branch'ini tespit edip silin: git ls-remote ... | grep shai-hulud ardından git push origin --delete shai-hulud komutunu çalıştırın

Rotate All Credentials Immediately

  • NPM token'ları, GitHub PAT/Actions secret'ları, SSH anahtarları, AWS/GCP/Azure kimlik bilgileri, DB bağlantı dizeleri, üçüncü taraf token'ları, CI/CD secret'ları dahil olmak üzere her şeyin tamamen değiştirilmesi gerekiyor
  • AWS Secrets Manager/GCP Secret Manager içinde saklanan öğeler dahil tam rotasyon gerekli

Audit Cloud Infrastructure for Compromise

  • AWS: CloudTrail içinde BatchGetSecretValue, ListSecrets, GetSecretValue çağrılarının zamanını ve desenlerini inceleyin; IAM Credential Report ile olağandışı anahtar oluşturma ve kullanımını kontrol edin
  • GCP: Audit Logs üzerinden Secret Manager erişim kayıtlarını inceleyin, CreateServiceAccountKey olaylarının olup olmadığını doğrulayın

1 yorum

 
GN⁺ 2025-09-17
Hacker News yorumu
  • npm’de barındırılan paketleri kullanan biri olarak, tüm bağımlılıkları ve onların bağımlılıklarını doğrudan izlemek gerçekçi bir yöntem gibi gelmiyor; ayrıca TypeScript/JavaScript uzmanı da değilim, bu yüzden saldırganın gizlediği kötü amaçlı kodu kolayca fark edebileceğimi sanmıyorum. Son dönemde düşündüğüm şey, güncellemeleri “gecikmeli mod” ile yapmak; yani en son sürüme değil, yalnızca belirli bir süre geçmiş sürümlere güncellemek. Bir paketin yaklaşık 6 hafta boyunca dış dünyaya açık kalması durumunda kötü amaçlı kodun ortaya çıkarılmış olma ihtimalinin yüksek olduğunu varsaymak gibi. Elbette bu kusursuz bir yöntem değil; güvenlik sorunu olduğunda istisnai olarak en güncel güncellemeyi hemen uygulamaya da izin veren bir araç olsa iyi olurdu

    • Makalede doğrudan bahsedilen yöntem olarak NPM Package Cooldown Check diye bir özellik var. Kurumun belirlediği süre içinde (varsayılan 2 gün) yayımlanmış bir paket sürümü pull request’e eklenirse derleme otomatik olarak başarısız oluyor. Tedarik zinciri saldırılarının büyük kısmı 24 saat içinde tespit edildiği için, çok kısa bir bekleme bile güvenlik maruziyetini azaltabiliyor

    • Tüm bağımlılıkları baştan sona incelemek zor olduğundan, mümkün olduğunca bağımlılık sayısını azaltmak ve yalnızca iyi bilinen, güvenilir paketleri kullanmak gerektiğini savunmak istiyorum. Hatta tüm yazarlarına güvenecek kadar kontrollü bir ortam yoksa, bir miktar 'not-invented-here' yaklaşımını korumak mantıklı bir tercih

    • package.json içinde sürümleri açıkça pin’leyip, package-lock.json içinde belirtilen sürümler dışında bir şey kurmamak için npm ci kullanma alışkanlığım var. CI’da npm audit çalıştırıp pakette zafiyet ortaya çıkarsa uyarı alıyorum. Bunu yapınca paketler neredeyse “dondurulmuş” hale geliyor ve yalnızca paketin yaşı bile bulaşma olasılığını azaltıyor

    • Ben bunun da ötesine geçip bağımlılıkları yalnızca bir hata gerçekten kendi kullanım ortamımı etkilediğinde güncelliyorum. Güvenlik açığı olsa bile beni etkilemiyorsa olduğu gibi bırakıyorum. Çoğu geliştirici bağımlılıkları gereksiz yere çok sık güncelliyor; bence doğru olan, sadece gerçekten gerektiğinde yapmak. Eğer güncelleme sık ya da karmaşıksa, o paketi hiç kullanmamak ya da benim ölçütüme göre “dondurmak” daha iyi

    • Python’un uv aracıyla da benzer şekilde güncellemeleri sınırlamak mümkün. Örneğin uv lock --exclude-newer $(date --iso -d "2 days ago") komutuyla son 2 gün içinde yayımlanan sürümleri hariç tutabilirsiniz

  • Bu tür sorunlar, yeni paketler ve sürümler yeterince izlenmediği için ortaya çıkıyor. Debian’daki gibi, yalnızca güvenlik yamaları ve hata düzeltmelerinin uygulandığı kararlı bir dağıtımı, paket bakımcılarının gözettiği testing/unstable dağıtımından ayrı işletmek en iyi yaklaşım olurdu. Merkezi açık paket depolarında (NPM, Python, Rust vb.) çalışan herkes aynı sorunla karşı karşıya

    • Geliştirici kültüründe bir sorun var. Yüzlerce (geçişli) bağımlılığa sahip olup bunları düşünmeden otomatik güncellemek başlı başına problem. Bu kadar çok üçüncü taraf kodunu derleme/çalıştırma ortamınıza maruz bırakma kararının bir sorumluluğu var

    • Dağıtımlar da bakımını üstlenmek zorunda oldukları paket miktarı yüzünden giderek daha fazla zorlanıyor. Aslında dil bazlı ekosistemler (ör. CPAN, Maven, RubyGems vb.) de bu yüzden gelişti; yalnızca Linux dağıtımları kullanıcıların istediği uygulamaları sunmakta yetersiz kalınca freshmeat, linuxbrew, flatpak, PPA gibi pek çok yol ortaya çıktı. Hiçbir topluluğun sayısız farklı kütüphanenin birden fazla dalını izleyip destekleyecek kapasitesi olduğunu sanmıyorum

    • Bir Debian geliştiricisi olarak, upstream kodu içeri almadan önce giderek artan “gürültü” yüzünden — özellikle yalnızca stil değişiklikleri ve araç güncellemeleri — gerçek değişiklikleri fark etmek çok zorlaşıyor. Bu tür değişiklikler, gerçekten insan incelemesi gerektiren refactor’lar, hata düzeltmeleri, özellik eklemeleri veya sorunlu olabilecek kodu bulmaya yönelik araç çıktıları değilse, keşke daha az yapılsa

    • Rust tarafında cargo vet diye bir sistem var. Google ve Mozilla gibi şirketler buna katılarak paketleri ortak biçimde otomatik olarak inceliyor ve doğruluyor

    • Merkezsiz yapıyı korurken yine de belli güvenlik önlemleri koymanın yolları olduğunu düşünüyorum. Örneğin belli büyüklüğün üzerindeki paketlerde 2FA kullanan iki hesabın onayı zorunlu olabilir ya da popüler paketlerin npm’e yüklenmesi yalnızca yeniden üretilebilir derleme sistemi üzerinden mümkün kılınabilir. Tam dağıtık yapıdan vazgeçmeden, yalnızca büyük projelerde biraz ek uğraş gerektiren çözümler düşünülebilir

  • Son dönemde art arda gelen tedarik zinciri saldırıları yüzünden sunucu taraflı render’ı (JavaScript olmadan) daha ciddi düşünmeye başladım. HTMX sayesinde JavaScript olmadan da gerçekten çok ileri gidilebildiğini fark ettim. Böyle olursa uygulama daha hızlı ve daha kararlı bile olabilir

    • Geleneksel JS ortamının aslında en güvenli sandbox ortamı olduğunu vurgulamak isterim. Yaklaşık 30 yıldır milyarlarca cihazda güvenilmeyen JS kodu çalışıyor ama tarayıcı motorlarına karşı büyük ölçekli başarılı saldırı örnekleri çok az. Buna karşılık NodeJS ve npm ortamı güvenlik açısından baştan aşağı yeniden tasarlanmalı. leftpad gibi olaylar, basit kod parçacıklarının bile npm’e paket olarak yüklenmesi kültüründen kaynaklanıyor

    • Bu saldırıların otomatik olarak yalnızca belirli bir ortama, yani JavaScript’e özgü bir meseleye indirgenmesi garip geliyor. Asıl daha büyük sorun, npm’de bulunan güvenlik güçlendirmelerinin bile başka ortamlarda (PyPI, Crates vb.) hiç bulunmaması gibi görünüyor

    • Vendoring maruziyeti azaltabilir ama bunun kökten çözüm olduğunu düşünmüyorum. NPM güvenliği gerçekten ciddiye alıyorsa, publish işlemi için 2FA’yı ve paket ön taramasını zorunlu kılmalı, hatta donanım anahtarıyla imzalamayı bile şart koşmalı. semver ya da CRC yeterli değil. Bunların hepsi paket yönetim sisteminin içine varsayılan olarak yerleşik gelmeli

    • Aslında bu saldırılar JavaScript’e özgü değil; geliştiricilerin yeni bağımlılık eklerken yeterince denetim yapmamasından doğuyor. Aynı şey Rust veya Go gibi diğer dil ekosistemleri için de geçerli olabilir

    • Paket yöneticilerine çok bağımlı olan ve standart kütüphanesi zayıf kalan tüm diller benzer şekilde savunmasız. Uzun vadede yeniden vanilla JavaScript kullanma yönüne dönmek gerektiğini düşünüyorum. Rust da aynı biçimde paket bağımlılığı açısından yüksek risk taşıyor. Hatta bu konuda Go daha örnek bir karşı örnek gibi duruyor

  • Güvenilir anahtarlarla commit/release imzalayan, kurulum ve doğrulamayı da yapan, hafif kodu izleyebilen bir sisteme ihtiyaç olduğunu düşünüyorum. Zaten sigstore kullanan npm provenance yaklaşımı mevcut, ancak henüz yaygın değil ve daha çok yayıncı doğrulamasıyla sınırlı gibi görünüyor

  • Bu zafiyet aslında 2016’da NPM’e rapor edilmişti (CERT tavsiyesi), ama NPM’in yanıtı WAI (working as intended) olmuştu

    • WAI’nin ne anlama geldiğini bilmeyenler için: Genelde “working as intended” kısaltmasıdır

    • postinstall betiği hiç olmasa bile, derleme sürecinde, sunucu başlatılırken ya da testlerde modül import edildiği anda kötü amaçlı kodun yine çalışacağını düşünüyorum. Sonuçta npm install sonrasında bir noktada gerçekten bir şey çalıştırmanız gerekecek...

  • left-pad olayında burada gördüğüm bir yorumu hatırladım; tanınmış bir npm bakımcısının 600 npm paketi ve 1.200 satır JavaScript kodu olduğundan bahsediliyordu. Örnek alınması gereken vaka bence esbuild; neredeyse hiç dış bağımlılığı yok ve yalnızca Go standart kütüphanesini kullanıyor
    “Yeni nesil” denen diğer projelerin bağımlılık zincirlerine bakınca biomejs ve swc de oldukça az görünüyor. Ama Rust kaynak koduna bakıldığında biomejs ve swc sonuçta yine çok sayıda bağımlılık taşıyor. Bu tür projeler yaygınlaşırsa cargo ekosisteminin de aynı yola gireceğini tahmin ediyorum. Eğer esbuild gibi katı bir tarzla yazılmış büyük projeler bilen varsa, öneri duymak isterim

    • Go’ya geçme nedenlerimden biri de purego tarzı kütüphane eğilimiydi. Genelde sadece standart kütüphane ve golang.org/x kullanıyorlar, CGO olmadan derlenebildikleri için taşınabilirlikleri yüksek. go mod vendor kısa vadeli risk yönetimi sağlayabilir ama kökten çözüm değil. Go tarafında da paket doğrulaması (imza/anahtar kontrolü vb.) uçtan uca sağlanmadığı için sonuçta açık kalıyor. Özellikle çok şey CI/CD altyapısında yoğunlaşmış durumda; imza anahtarlarını aktarmadan da derleme ve dağıtım yapılabiliyorsa güvenlik daha da artabilir diye düşünüyorum. Paket yöneticileri GPG imzalarını teşvik etmeli, git commit’lerinde de imza kullanımı yaygınlaştırılmalı

    • eslint vakası özellikle can sıkıcı geliyor. Bağımlılık grafiğine bakınca devasa olduğu görülüyor; bakımcılar bağımlılık azaltımını önceliklendirmiyorsa sonunda başka bir çözüme (oxlint) geçmekten başka çare kalmıyor

    • Basit özellikleri kendin yazıp dış bağımlılıkları azaltmak çözümün bir parçası. Genelde bunu yapmak bile toplam bağımlılıkların 2/3’ünü azaltabiliyor. Özellikle left-pad gibi basit şeyleri kendin yazıp küçük birimler ve testlerle kendi kontrolünde tutarsan bakım yükü de çok artmıyor. Gereksiz bağımlılıklar kararlılıkla dışarıda bırakılmalı

    • Bir Rust projesinin kök Cargo.toml dosyasında görülenler tüm workspace içindir; her crate’in gerçek bağımlılıkları çok daha sığ olabilir. Gerçek bağımlılık yapısını anlamak için daha derine bakmak gerekir

    • Bunun kötü yanı, artık JavaScript projelerini denetlemek için Golang da okumak zorunda olmanız. Üstelik post-install sırasında yine node install.js çalışıyor; sonuçta ya tamamen güveneceksiniz ya da tüm kodu okuyacaksınız

  • npm’in hâlâ varsayılan olarak tüm bağımlılıkların postinstall betiklerini çalıştırıyor olmasına inanamıyorum. Pnpm veya Bun bunu yalnızca izin listesine alınmışsa çalıştırıyor; Composer ise bağımlılıklar için lifecycle script’lerini hiç çalıştırmıyor. Derleme ya da geliştirme ortamında bağımlı paketlerin taşıdığı risk yüzünden bu yaklaşımın daha güvenli olduğunu düşünüyorum

    • Bu kadar büyük saldırıların diğer paket yöneticilerinde (ör. Rust build.rs, Python, Java vb.) neden bu kadar sık duyulmadığını merak ediyorum. postinstall bir yana, aslında neredeyse tüm ekosistemlerde ilke olarak mümkün; ama olaylar sanki özellikle npm etrafında yoğunlaşıyor

    • Pnpm’in varsayılanının betikleri engelleyecek şekilde değiştiğini gördüm. Topluluğun buna tepkisini — betik izni verildiğinde kullanıcı deneyimi, allow komutunun kötüye kullanımı vb. — merak ediyorum. Python paketleme topluluğunda da wheel variants ile ilgili benzer tartışmalar sürüyor; başka ekosistemlerin deneyimlerinden faydalanmak isterim

  • Bu saldırı 180’den fazla pakete yayılmış durumda; bkz. Aikido Security blogu

  • Bu saldırıyı ilk kimin keşfettiğini merak ediyorum. Farklı bloglar krediyi farklı yerlere veriyor, bu da ilginç. Aikido “büyük ölçekli saldırıyı biz keşfettik” diyor; Socket, Ox, Safety, Phoenix, Semgrep vb. de olayı kendi biçimlerinde anlatıyor

    • Ben Aikido’da çalışan Mackenzie’yim. Bu konuyu ilk bildiren kişi geliştirici Daniel Pereira’ydı; kendisi bunu Socket’e iletti ve Socket ilk 40 paketi ve kötü amaçlı yazılımı analiz etti. Sonrasında Aikido ek 147 paket ile Crowdstrike paketini de buldu. Aslında kötü amaçlı yazılımın kendi kendine yayılan bir worm olduğunu ilk fark eden de Step’ti. Birden fazla kuruluşun bağımsız biçimde farklı roller üstlenmiş olması ilginç

    • Görünüşe göre birçok geliştirici bunu neredeyse aynı zamanlarda fark etti ve Step ile Socket farklı kişileri anıyor. Sonuçta sektörün güvenlik sağlayıcıları bunu kendi yöntemleriyle yakaladı: yapay zeka kod analizi (Socket, Aikido) ya da eBPF pipeline izleme (Step) gibi

    • Bu kadar çok sağlayıcı bunu bağımsız olarak tespit edebildiyse, acaba bu teknikleri doğrudan npm ile paylaşsalar kötü amaçlı paketlerin kaydedilmesi en baştan engellenebilir miydi diye düşünüyorum. O zaman erken uyarı sistemlerini satamaz hale gelecekleri için paylaşmıyor olabilirler

    • OP’deki makale doğrudan şu ifadeyi alıntılıyor: “@franky47 bu olguyu fark edip topluluğu hızla bir GitHub sorunu üzerinden bilgilendirdi”

  • Saldırganın seçtiği “Shai Hulud” adını epey zekice buluyorum; dev bir solucanın adını gerçek bir worm zararlısına vermiş. Ana bundle.js dosyası da 3.6MB ile oldukça devasa. Varyant kötü amaçlı yazılım bile npm usulü gereğinden büyük hale gelmiş

    • Yakında bir tedarik zinciri saldırısının tesadüfen başka bir tedarik zinciri saldırısını da tetikleyeceğine dair bir his var içimde

    • Zararlı yazılımlar da Moore yasasına uyuyor; 1991’deki tequila virus 2.6KB idi, şimdi ise birkaç MB boyutundalar