Alesta WEB

Sabah kalktınız, projenizde npm install çalıştırdınız ve hiçbir şey olmadı gibi göründü. Peki ya olduysa? 4 Ağustos 2026'da başlayan npm tedarik zinciri saldırısı (npm supply chain attack) tam olarak böyle işliyor: kurulum bitmeden, testleriniz çalışmadan önce sisteminizde kod yürütüyor. Alesta Web olarak bu rehberde ChainDrop — namıdiğer "Mini Shai-Hulud" — solucanının nasıl yayıldığını, hangi paketleri vurduğunu ve sunucunuzu, bilgisayarınızı nasıl temizleyeceğinizi adım adım anlatıyoruz.
Kısaca Ne Oldu? (What Happened in the npm Supply Chain Attack)
Olay şöyle gelişti. Saldırganlar, çok kullanılan bir npm paket ailesinin bakımcısına ait hesabı ele geçirdi. Elde ettikleri yayınlama yetkisiyle paketlerin yeni sürümlerini kendileri yayınladılar. Ama bu sürümler normal bir güncelleme değildi: içlerine kimlik bilgisi çalan, üstelik kendi kendini çoğaltan bir zararlı yazılım yerleştirilmişti.
İşin can sıkıcı tarafı şu: bu npm tedarik zinciri saldırısı tek bir pakette kalmadı. Zararlı yazılım, çaldığı npm token'ıyla o kimliğin erişebildiği diğer paketleri de zehirledi. Yani bir solucan (worm) gibi yayıldı. Microsoft'un güvenlik ekibinin analizine göre kısa sürede 400'ün üzerinde paket sürümü bu şekilde yayınlandı.
Bu makaleyi okuyorsanız ve son bir hafta içinde Node.js projelerinizde bağımlılık kurduysanız, etkilenmiş olma ihtimaliniz gerçek. Aşağıdaki "Tespit" bölümünü atlamayın. Alesta Web ekibi olarak müşteri sunucularımızda ilk yaptığımız iş bu taramaydı.
Rakamlar konuyu daha net anlatıyor. Saldırıdan etkilenen ailedeki paketlerin bazıları haftada yüz milyonlarca kez indiriliyor. flat-cache ve file-entry-cache gibi kütüphaneler doğrudan sizin projenizde olmasa bile, kullandığınız bir test aracının ya da linter'ın bağımlılığı olarak sisteminize girmiş olabilir. Bu, klasik bir npm supply chain attack senaryosudur: siz hiçbir şey yapmasanız da, bağımlılığınızın bağımlılığı sizi vurur.
ChainDrop / Shai-Hulud Solucanı Nedir? (What is the Shai-Hulud Worm?)
Adına Microsoft "ChainDrop" diyor, güvenlik topluluğu ise "Mini Shai-Hulud" olarak anıyor. İsim, daha önce benzer bir yöntemle yayılan bir zararlıdan geliyor. Teknik olarak tanımı şu: Bun tabanlı, ağır şekilde karartılmış (obfuscated), kendi kendini çoğaltan bir kimlik bilgisi hırsızı.
Şimdi bunu sadeleştirelim. Klasik bir zararlı yazılım bir dosyaya bulaşır ve orada durur. Bu solucan farklı çalışıyor:
Yayılma Döngüsü / Propagation Loop
1. Bakımcının npm token'ı ele geçirilir 2. Zararlı, o token ile erişilebilen TÜM paketleri listeler 3. Her paketin son tarball'ı indirilir 4. İçine zararlı + setup.mjs yükleyicisi eklenir 5. package.json'a "preinstall" hook'u eklenir 6. Patch sürümü artırılır (ör. 5.3.1 -> 5.3.2) 7. Paket yeniden yayınlanır -> yeni kurbanlar 8. Yeni kurbanın token'ı çalınır -> 1. adıma dön
Bu döngü, saldırının neden bu kadar hızlı büyüdüğünü açıklıyor. Her yeni kurban, yeni bir yayılma noktası oluyor. Klasik bir npm tedarik zinciri saldırısı tek bir bakımcıyla sınırlı kalırken, bu solucan bakımcıdan bakımcıya atlıyor.
Zararlı sürümlerin çoğunda GitHub tarafında karşılık gelen bir commit, pull request ya da tag yok. Yani kaynak koda bakıp "temiz görünüyor" demek yetmiyor. Kod deposu temiz olabilir ama npm'e yüklenen tarball zehirli olabilir. Bu ayrım çok önemli, çünkü çoğu ekip sadece kaynak koda bakıyor.
Etkilenen Paketler (Affected npm Packages)
Saldırının merkez üssü, önbellekleme (caching) araçları üreten bir paket ailesiydi. Aşağıdaki tablo, en çok konuşulan paketleri ve yaklaşık indirme hacimlerini gösteriyor. Rakamlar kamuya açık güvenlik raporlarından derlenmiştir.
| Paket / Package | İşlevi / Purpose | Yaklaşık İndirme |
|---|---|---|
keyv |
Anahtar-değer depolama (key-value storage) | ~127 milyon / hafta |
flat-cache |
Dosya tabanlı önbellek (file cache) | ~565 milyon / ay |
file-entry-cache |
ESLint önbellek altyapısı | ~557 milyon / ay |
cacheable |
Önbellek katmanı (caching layer) | ~29 milyon / ay |
cache-manager |
Çok katmanlı önbellek yöneticisi | Yüksek |
Listeye bakıp "ben bunları kullanmıyorum" demeyin. file-entry-cache paketini doğrudan kuran neredeyse yok; ama ESLint kullanan herkesin node_modules klasöründe duruyor. Alesta Web olarak incelediğimiz projelerin büyük kısmında bu paketler dolaylı bağımlılık (transitive dependency) olarak yer alıyordu.
Toplamda 1.300'ü aşkın paket sürümünün etkilendiği, bu sürümlerin birleşik aylık indirme hacminin milyarlarla ifade edildiği raporlandı. Bu ölçek, olayı 2026'nın en geniş çaplı npm tedarik zinciri saldırısı yapıyor.
Saldırı Nasıl Çalışıyor? preinstall Tuzağı (How the Attack Works)
Şimdi işin teknik kısmına gelelim. Bunu anlamanız önemli, çünkü korunma yöntemi doğrudan buradan çıkıyor.
1. npm lifecycle script'leri
npm, bir paketi kurarken belirli aşamalarda paketin kendi tanımladığı komutları çalıştırır. Bunlara lifecycle script denir. preinstall, adından da anlaşılacağı gibi kurulum tamamlanmadan önce çalışır.
Zehirli package.json / Malicious package.json
{
"name": "ornek-paket",
"version": "5.3.2",
"scripts": {
"preinstall": "node setup.mjs"
}
}
Kritik nokta şurada: bu komut, siz henüz kodu incelemeden, testler çalışmadan, güvenlik taramanız devreye girmeden yürütülür. Yani geliştirici bilgisayarında ve CI/CD sunucusunda kod çalıştırma imkânı, npm install yazdığınız anda saldırganın eline geçer.
2. İkinci aşama: Bun ile karartılmış yük
setup.mjs dosyası tek başına zararsız görünür. Yaptığı iş, bağımsız bir Bun çalışma zamanı (runtime) indirmek ve asıl karartılmış paketi onunla çalıştırmaktır. Neden Bun? Çünkü sistemde kurulu Node.js'in güvenlik eklentileri, izleme araçları ya da sürüm kısıtları devreden çıkmış olur. Saldırgan kendi getirdiği yorumlayıcıyı kullanır.
Sisteminizde node_modules altında bun-dl- ile başlayan klasörler ya da Math_Symbol.js, Math_init.js gibi tuhaf isimli dosyalar görüyorsanız bu ciddi bir uyarı işaretidir. Hemen "Temizlik" bölümüne geçin.
3. Sızdırma kanalı
Toplanan veriler JSON'a çevrilir, gzip ile sıkıştırılır, rastgele bir anahtarla AES-256-GCM kullanılarak şifrelenir; anahtar da saldırganın RSA açık anahtarıyla korunur. Ana kanal saldırganın kontrolündeki bir HTTPS adresidir. O kanal kapanırsa zararlı, kurbanın GitHub hesabında herkese açık bir depo oluşturup şifreli veriyi oraya commit eder.
Bu, savunma açısından ilginç bir detay: engellediğiniz tek bir alan adı saldırıyı durdurmuyor. Bu yüzden npm supply chain attack vakalarında ağ seviyesinde engelleme tek başına yeterli bir çözüm değildir.
Hangi Bilgiler Çalınıyor? (Which Credentials Are Stolen)
Zararlı yalnızca dosyalarda token deseni aramıyor. Bulduğu kimlik bilgileriyle gerçekten API çağrısı yapıp erişimi doğruluyor ve o kimliğin ulaşabildiği başka sırları da topluyor. Hedef listesi:
- ✅ npm yayınlama token'ları (npm publish tokens)
- ✅ GitHub CLI token'ları ve depo erişimi (repository access)
- ✅ AWS kimlik bilgileri (AWS credentials)
- ✅ Kubernetes küme erişim bilgileri (cluster credentials)
- ✅ HashiCorp Vault sırları (Vault secrets)
- ✅ SSH anahtarları ve bulut yapılandırma dosyaları
- ✅ Kabuk geçmişi ve ortam değişkenleri (shell history, environment variables)
- ✅ GitHub Actions çalıştırıcı belleği ve OIDC token'ları
Son madde özellikle sinsi. CI/CD ortamınızda çalışan bir npm install, o iş akışına verilmiş bulut yetkilerini de ele verebilir. Yani bir geliştiricinin dizüstü bilgisayarıyla sınırlı kalmayan, doğrudan üretim altyapınıza uzanan bir risk söz konusu.
Ek olarak zararlı, çaldığı GitHub yetkisiyle depolara kalıcılık bırakmaya çalışıyor: editör ve yapay zekâ asistanı yapılandırma yollarına kendi dosyalarını enjekte ediyor. Alesta Web olarak müşteri projelerinde bu tip yapılandırma dosyalarını da ayrıca denetlemenizi öneriyoruz.
Etkilendim mi? Tespit Komutları (How to Detect the Compromise)
Panik yapmadan, sırayla ilerleyelim. Aşağıdaki komutlar hem yerel makinenizde hem sunucunuzda çalışır.
Adım 1: Şüpheli yükleyici dosyalarını ara
Linux / macOS
# Zararlı yükleyici izleri find . -path ./.git -prune -o -name "setup.mjs" -print find . -name "Math_Symbol.js" -o -name "Math_init.js" # Indirilmis Bun calisma zamani izi find . -type d -name "bun-dl-*"
Windows PowerShell
Get-ChildItem -Recurse -Filter setup.mjs -ErrorAction SilentlyContinue Get-ChildItem -Recurse -Include Math_Symbol.js,Math_init.js -ErrorAction SilentlyContinue
Adım 2: preinstall hook'u olan bağımlılıkları listele
Tüm preinstall script'lerini gör
grep -rl '"preinstall"' node_modules/*/package.json 2>/dev/null
# Daha okunakli cikti
for f in node_modules/*/package.json; do
node -e "const p=require('./$f'); if(p.scripts&&p.scripts.preinstall) console.log(p.name, '->', p.scripts.preinstall)" 2>/dev/null
done
Meşru paketlerin de preinstall kullandığını unutmayın (özellikle native modüller). Amaç her sonucu silmek değil, node setup.mjs gibi tanımadığınız komutları yakalamak.
Adım 3: Kurulu sürümleri kontrol et
Etkilenen aileyi sorgula
npm ls keyv cacheable flat-cache file-entry-cache cache-manager # Kilit dosyasinda hangi surumler var? grep -A2 -E '"(keyv|cacheable|flat-cache|file-entry-cache)"' package-lock.json | head -40
Adım 4: Ağ ve süreç izlerine bak
Kurumsal ortamdaysanız, uç nokta tespit çözümünüzde şu davranışları arayın: node sürecinin setup.mjs çalıştırması, ardından node tarafından bir bun ikilisinin başlatılması, ve bun sürecinin gh auth token ya da az account get-access-token gibi komutları çağırması. Bu zincir, normal bir geliştirme akışında görülmez.
Yukarıdaki dört adım da temiz çıktıysa büyük ihtimalle etkilenmediniz. Yine de "Korunma" bölümündeki min-release-age ayarını uygulayın — bir dahaki sefere hazırlıklı olursunuz.
Temizlik ve Kurtarma Adımları (Remediation Steps)
Şüpheli bir iz bulduysanız sıra kritik kısımda. Buradaki sıralama önemli: önce kimlik bilgilerini iptal edin, sonra temizleyin. Tersini yaparsanız, temizlik sürerken çalınmış token hâlâ geçerli olur.
Adım 1: Token'ları temiz bir makineden iptal edin
Token iptal işlemini etkilenen makineden yapmayın. Zararlı hâlâ aktifse yeni ürettiğiniz token'ı da çalar. Temiz bir bilgisayar ya da telefon üzerinden web arayüzünü kullanın.
- npm: tüm yayınlama token'larını iptal edin, 2FA'yı zorunlu hale getirin
- GitHub: personal access token'ları ve SSH anahtarlarını yenileyin
- Bulut sağlayıcı: erişim anahtarlarını döndürün (rotate)
- CI/CD: depo sırlarını (secrets) baştan oluşturun
Adım 2: Bağımlılıkları sıfırdan kurun
Tam temizlik / Full clean install
# Kirli klasoru ve onbellegi kaldir rm -rf node_modules npm cache clean --force # Kilit dosyasindaki surumlerle, script calistirmadan kur npm ci --ignore-scripts # Sonra sadece guvendigin paketlerin build adimini elle calistir npm rebuild --foreground-scripts
--ignore-scripts bayrağı burada hayat kurtarıcı. Kurulum sırasında hiçbir lifecycle script'i çalışmaz; böylece zehirli bir sürüm sisteminize hâlâ inse bile kod yürütemez.
Adım 3: Sürümleri bilinen iyi noktaya sabitleyin
Güvenli sürüme dönüş / Pin to a known-good version
# Ornek: saldiri oncesi bir surume sabitle npm install keyv@5.3.1 --save-exact # package.json'da caret kaldirildi mi kontrol et grep -E '"(keyv|cacheable)"' package.json
Adım 4: CI önbelleklerini ve yapı sunucularını temizleyin
Bu adım sık atlanıyor. Geliştirici makinesini temizlersiniz ama CI sunucusundaki node_modules önbelleği zehirli kalır ve bir sonraki derlemede sorun geri döner. Yapı önbelleğini (build cache) tamamen geçersiz kılın, artifact deposundaki kirli sürümleri karantinaya alın.
Adım 5: Doğrulayın
Temizlik doğrulaması / Verification
# Iz kalmadigini dogrula find . -type d -name "bun-dl-*" | wc -l # 0 olmali grep -rl "setup.mjs" node_modules 2>/dev/null | wc -l # 0 olmali # Bagimlilik agacinda bilinen kotu surum var mi? npm audit
Kalıcı Korunma: npm 12 ve min-release-age (Long-Term Protection)
Tek seferlik temizlik iyi, ama asıl mesele bir dahakine hazırlıklı olmak. Bu tür bir npm tedarik zinciri saldırısı yılda birkaç kez tekrarlanıyor ve her seferinde daha rafine hale geliyor.
1. Sürüm bekletme (min-release-age)
npm 12 ile gelen bu özellik basit ama çok etkili bir fikre dayanıyor: yeni yayınlanmış bir sürümü hemen kurma, birkaç gün beklet. Kötü niyetli sürümler genellikle saatler içinde fark edilip kaldırılıyor. Siz 3 gün beklerseniz, o pencereyi tamamen atlarsınız.
npm 12 ve bekletme ayarı
# npm'i guncelle npm install -g npm@12 npm --version # Yeni surumleri 3 gun beklet npm config set min-release-age 3d # Proje bazinda: .npmrc dosyasina ekle echo "min-release-age=3d" >> .npmrc
2. CI'da script'leri kapatın
CI/CD sertleştirme / CI hardening
# .npmrc (repo koku) ignore-scripts=true audit=true # CI adimi npm ci --ignore-scripts
3. Kilit dosyasını ciddiye alın
package-lock.json dosyasını sürüm kontrolüne mutlaka ekleyin ve CI'da npm install yerine npm ci kullanın. npm ci yalnızca kilit dosyasındaki tam sürümleri kurar; sizin haberiniz olmadan yeni bir sürüm çekmez.
4. Token yetkilerini daraltın
- Yayınlama token'larını yalnızca yayın iş akışına verin, genel CI'ya değil
- Mümkünse granular (paket bazlı) token kullanın
- Süresiz token üretmeyin; kısa ömür + otomatik yenileme tercih edin
- GitHub Actions'ta OIDC ile geçici kimlik kullanın
Müşteri projelerimizde uyguladığımız pratik kural şu: üretim derlemesi (production build) internete paket indirmek için çıkmaz. Bağımlılıklar önceden doğrulanmış bir iç ayna (mirror) üzerinden gelir. Böylece npm tarafında ne olursa olsun, üretim hattınız etkilenmez.
Sık Sorulan Sorular (Frequently Asked Questions)
❓ Paketi kurmadım, sadece indirdim. Risk var mı?
Evet. preinstall hook'u kurulum tamamlanmadan çalıştığı için, indirme ve çıkarma aşamasını geçen her komut riskli. npm install yazdıysanız kurulum "başarısız" bitse bile kod çalışmış olabilir.
❓ Yarn veya pnpm kullanıyorum, etkilenir miyim?
Evet. Sorun paket yöneticisinde değil, npm kayıt defterindeki (registry) zehirli paketlerde. Yarn ve pnpm de aynı paketleri aynı kayıt defterinden çeker. İyi haber: pnpm ve yarn tarafında da script çalıştırmayı kısıtlayan ayarlar var.
❓ npm audit temiz diyor, rahat olabilir miyim?
Tam olarak değil. npm audit bilinen ve kaydedilmiş güvenlik açıklarını gösterir. Yeni yayınlanmış zehirli bir sürüm veri tabanına işlenene kadar orada görünmez. Bu yüzden dosya seviyesindeki taramayı da yapın.
❓ Etkilendiysem müşteri verilerim de gitti mi?
Zararlı doğrudan veri tabanı içeriği kopyalamıyor; kimlik bilgisi topluyor. Ancak çalınan bir bulut anahtarı ya da SSH anahtarı, saldırgana veriye erişim yolu açabilir. Bu yüzden anahtar döndürme (key rotation) adımı ertelenmemeli.
📚 Kaynaklar ve Referanslar / Sources and References
Bu makaledeki teknik bilgiler aşağıdaki kamuya açık güvenlik analizlerinden derlenmiş ve Alesta Web ekibi tarafından doğrulanmıştır:
- Microsoft Security Blog — ChainDrop supply chain compromise · Solucanın teknik anatomisi ve tespit sorguları
- Singapur Siber Güvenlik Ajansı (CSA) — Advisory AD-2026-009 · Resmî uyarı ve etkilenen paket listesi
- Socket — keyv ve cacheable namespace analizi · Etkilenen sürüm ve indirme istatistikleri
- Datadog Security Labs — npm worm analizi · Yayılma mekanizması
- npm Docs — Lifecycle Scripts · preinstall ve diğer hook'ların resmî dokümantasyonu
✅ Özetle: Ne Yapmalısınız? (Quick Summary)
Bu npm tedarik zinciri saldırısı bize şunu hatırlattı: bağımlılık listeniz aslında güven listenizdir. Alesta Web olarak geliştirdiğimiz tüm projelerde kilit dosyası disiplini ve script kısıtlaması standarttır — bu olaydan sonra bunu daha da sıkılaştırdık.
Hızlı Özet / Quick Summary:
- ✅
setup.mjsvebun-dl-*izlerini tarayın (scan for indicators) - ✅ Şüphe varsa token'ları temiz bir makineden iptal edin (rotate credentials)
- ✅
rm -rf node_modules+npm ci --ignore-scriptsile temiz kurulum - ✅ CI önbelleklerini de temizleyin, sadece dizüstünüzü değil
- ✅ npm 12 +
min-release-age=3dile bir dahakine hazırlanın - ✅ Kilit dosyasını sürüm kontrolüne alın,
npm cikullanın
Faydalı Bağlantılar / Useful Links:
- Alesta Web Ana Sayfa: alestaweb.com — yazılım ve altyapı çözümleri
- Diğer Teknoloji Rehberleri: alestaweb.com/haberler — güncel yazılım ve güvenlik içerikleri
Sunucunuzda ya da projenizde bu saldırıya dair bir iz bulduysanız ve nasıl ilerleyeceğinizden emin değilseniz, Alesta Web ekibiyle alestaweb.com üzerinden iletişime geçebilirsiniz. Tecrübemize göre en kritik saat, ilk 24 saattir.
© 2026 Alesta Web — Tüm hakları saklıdır.

