31 Mart 2026 sabahı Slack’te bir müşteri kanalına şu mesaj düştü: “Build agent’ımız garip bir IP’ye dışarı bağlantı kuruyor, bir bakar mısın?” Açık konuşayım, kahvemi bitirmemiştim bile, üstümde de o klasik sabah sersemliği vardı. Ama o tek mesaj, gün boyu uzayan bir tedarik zinciri stresinin başlangıcı öldü.
Hani, Hadise şu: Axios — yanı neredeyse her Node.js projesinde karşınıza çıkan, JavaScript tarafında baya iş gören HTTP client kütüphanelerinden biri — npm registry’de kısa süreliğine zehirlendi. 1.14.1 ve 0.30.4 sürümleri, kurulum sırasında çalışan gizli bir bağımlılık taşıyordu. Bu bağımlılık saldırganın komuta-kontrol (C2) altyapısına bağlanıyor, sonra da ikinci aşama payload’unu indiriyordu; hani insan ilk bakışta anlamıyor ama işin aslı pek hoş değil.
Çok konuştum, örnekle göstereyim.
Yanı npm install yazdığınız anda mesele kapanıyordu. Build agent’ınızda ne kadar credential varsa, ortam değişkenlerinde ne saklıysa, hepsi risk altındaydı.
Önce Şunu Netleştirelim: Azure Pipelines Hacklenmedi
İlk gün ortalık biraz karışıktı. “Azure Pipelines mı patladı?” diye sorular geldi, hatta bazı ekipler log ekranını açıp dakikalarca aynı satırlara baktı. Hayır. Lafı gevelemeden söyleyeyim: Azure Pipelines’ın kendisi etkilenmedi. Bu bir platform açığı değil; bildiğiniz npm ekosistemine yapılan tedarik zinciri saldırısı.
Microsoft-hosted agent kullanan ve sadece Microsoft’un yazdığı built-in task’leri çalıştıran müşteriler, altyapı tarafında güvende sayılır (buna dikkat edin) (eh, fena değil). Çünkü hosted agent her job için yeni bir VM açıyor, iş bitince de o VM’i çöpe atıyor. Persistence yok. Bir job’a bulaşan şeyin sonraki job’a sıçraması kolay değil; yanı sistemin mantığı bu konuda fena değil.
Vallahi, Gel gelelim — burası kritik nokta — pipeline içinde sizin yazdığınız npm install komutu çalıştıysa ve o anda zehirli versiyon çekildiyse, o job süresince agent’a verilen secret’lar, token’lar, service connection credential’ları… açık konuşayım, bunların hepsi sızmış kabul edilir. Platform değil sorun; sizin kodunuzun çağırdığı bağımlılık zinciri sorun.
“Microsoft-hosted agent kullanıyorsanız platform güvende olabilir, ama pipeline’ınızın saldırgana geçit vermediği anlamına gelmez. İkisi aynı şey değil.”
Hangı Versiyonlar, Hangı Pencere?
Bi saniye — Etkilenen versiyonlar kısaca şöyle:
| Paket | Zehirli Versiyon | Risk |
|---|---|---|
| axios | 1.14.1 | Kurulum sırasında C2 bağlantısı |
| axios | 0.30.4 | Aynı pattern, eski sürüm dalı |
Saldırı penceresi kısaydı; npm güvenlik ekibi paketleri hızlıca kaldırdı (ben de ilk duyduğumda şaşırmıştım). Ama “kısa” derken yine de saatler düzeyinde bir aralıktan söz ediyoruz. O sırada dünya genelinde binlerce CI pipeline’ı koşuyordu zaten. Evet, kulağa küçük geliyor ama öyle pek de küçük değil.
Bulaştınız mı, Nasıl Anlarsınız?
İlk işiniz build log’larını taramak olsun; özellikle saldırı penceresine denk gelen job’lara bakın. Pipeline’larınızda Axios’un bu spesifik versiyonları çekildi mi? package-lock.json, npm-shrinkwrap.json, hatta transitif bağımlılıklar içinde iz var mı? Bazen paket sizden çıkmıyor gıbı görünür ama sizin kullandığınız başka bir paketin içinden sessizce gelir; işte orası biraz sinsidir. Daha fazla bilgi için GitHub App Token Formatı Değişiyor: ghs_ Sonrası Yeni Dönem yazımıza bakabilirsiniz.
# Repository genelinde hızlı kontrol
grep -r "1.14.1\|0.30.4" --include="package-lock.json".
grep -r "1.14.1\|0.30.4" --include="yarn.lock".
# npm ls ile bağımlılık ağacında ara
npm ls axios
Self-Hosted Agent Kullanıyorsanız İşler Değişir
Tuhaf ama, Microsoft-hosted agent tarafında en azından “her job temiz VM” rahatlığı var. Ama self-hosted agent bambaşka hikâye; kendi sunucunuzda duruyor. Cache kalıyor, npm cache klasörü kalıyor, yanlış bir script çalıştıysa persistence bile bırakabiliyor. Bu konuyla ilgili Kubelet Fine-Grained Authorization GA: nodes/proxy Devri yazımıza da göz atmanızı tavsiye ederim.
Neyse ki geçen yıl bir telekom müşterimizde bunu bizzat konuşmuştuk da konuya yabancı değildik. Jenkins’ten Azure DevOps’a göç ediyorduk. Ekip self-hosted agent istedi; sebep de on-prem kaynaklara erişim ihtiyacıydı ki bu gayet mantıklıydı aslında. Ama o süreçte şunu net gördük: self-hosted agent — hele uzun ömürlü olanlar — neredeyse production sunucusu gıbı ele alınmalı; patch yönetimi var, izolasyon var, credential rotation var… Mantıklı değil mi? hiçbirini “sonra bakarız” diye bırakamıyorsunuz. SELinux Volume Label Değişiklikleri GA: v1.37’de Neler yazımızda bu konuya da değinmiştik.
Şunu söyleyeyim, This olay tam da önü gösteriyor gıbı düşünün biraz:
- Reimage edin. Yamayı düşünmek yerine sistemi baştan kurun; tartışmaya açık değil.
- Npm cache’i temizleyin, global node_modules klasörlerini silin (reimage yapamıyorsanız bile bunu yapın).
- Tüm credential’ları rotate edin: PAT’ler, service connection secret’ları, Azure subscription credential’ları, container registry token’ları… hepsi. — bunu es geçmeyin
- Ağ log’larına bakın: Tanımadığınız IP adreslerine outbound trafik olmuş mu? — bunu es geçmeyin
Bir job için açılır, biter ve VM ölür gider.
Tıpkı hosted agent gıbı davranır ama sizin networkünüzün içinde kalır.
Container Build’ler Ayrı Bir Hikâye’
Eğer pipeline’ınız Docker image build ediyorsa ve o image’ın içinde npm install çalışıyorsa işler daha da karışır; çünkü zehirli paket yalnızca agent’a bulaşmış olmaz, ürettiğiniz artifact’ın içine de yerleşebilir.
Yanı kirlenen sadece çalışma ortamı değildir.
Container registry’nizde saldırı penceresinde push edilen image’ları ayırın,
tarayın,
gerekirse silin;
burası biraz can sıkıcı ama yapılmadan geçilmiyor.
Türkiye’deki Şirketler Açısından Durum’
Bunu ayrıca konuşalım çünkü Türkiye’deki kurumsal yapı biraz farklı akıyor.
Açık söyleyeyim:
Yurt dışındaki şirketlerde “supply chain attack” konusu son 2-3 yılda baya olgunlaştı.
SBOM konuşuluyor,
dependency scanning standart hâle geliyor,
hatta bazı yerlerde kim hangı paketi neden ekledi diye soruluyor.
Bizde işe hâlâ birçok şirket pipeline’da ne çalıştığını tam bilmiyor;
biraz acıtıcı. Gerçek bu.
Hmm, bunu nasıl anlatsamdı… Bu konuyla ilgili azure ile ilgili önceki yazımız yazımıza da göz atmanızı tavsiye ederim. Gateway API v1.5: Stable’a Taşınan Özellikler ve Notlarım yazımızda bu konuya da değinmiştik.
Bakın, Daha geçen ay bir bankacılık müşterimde audit yaparken sordum:
“Peki pipeline’lardaki dış bağımlılıklar nereden geliyor?”
Cevap kısa geldi:
“npm.org’dan otomatik.”
Bak şimdi,
bu cevap tek başına yeterince şey anlatıyor zaten;
public npm registry’e doğrudan açık bir build farm,
2026 yılında bankada görmek istemeyeceğiniz türden bir tablo.
Emin değilim. Sanırım en çok buraya takılmamız gerekiyor.
Şahsen, Tavsiyem şu:
özellikle finans,
kamu,
sağlık gıbı regülasyonlu sektörlerde Azure Artifacts upstream feed‘i kullanın.
Public npm’i doğrudan çekmek yerine kendi feed’inizin arkasından alın.
Bir paket onaylandıktan sonra cache’lensin;
public registry’de biri zehir yayınlasa bile sizin feed’inizdeki temiz sürüm korunur.
Maliyeti?
Aylık birkaç dolar civarı.
Faydası?
Bu tıp bir günü yaşamamak.
Bence hesap basit.
Bir dakika — bununla bitmedi.
Kurum İçi vs Startup: Aynı Olay, Farklı Aksiyon
Küçük bir ekipseniz — mesela 3-5 kişiyseniz ve full-stack projede dönüp duruyorsanız — aksiyon listeniz kısa ölür:
package-lock.json‘a bakın; zehirli versiyon var mı kontrol edin.- Eğer yoksa rahat nefes alın ama Dependabot ya da Renovate gıbı bir tool’u şimdi kurun. >Pipeline secret’larınızı rotate edin; zarar vermez, garanti sağlar.
Sıkça Sorulan Sorular
Microsoft-hosted agent kullanıyorum, hiçbir şey yapmama gerek yok mu?
Platform güvende, tamam. Ama pipeline’ınız yine de sizin sorumluluğunuzda. Yanı saldırı penceresiyle çakışan bir build aldıysanız ve o sırada npm install çalıştırdıysanız, o job’a verilen secret’ları rotate etmenizi öneririm. Açıkçası hosted agent’ın temiz olması, sizin paketinizin de temiz olduğu anlamına gelmiyor.
package-lock.json’da zehirli versiyonu görmüyorum, garanti güvende mıyım?
Direkt bağımlılığınızda yoksa iyi haber tabii. Ama mesela kullandığınız başka bir paketin bağımlılığı olarak, yanı transitif bağımlılık şeklinde gelmiş olabilir. npm ls axios komutunu çalıştırın ve tüm ağacı tarayın. Yarn kullanıyorsanız yarn why axios daha pratik ölür.
Self-hosted agent’ımı reimage etmem şart mı?
Saldırı penceresinde build aldıysanız ve zehirli paket çekildiyse — evet, şart. Yamamak yerine baştan kurun. Çünkü malware’in nelere bulaştığını tahmin etmek aslında neredeyse imkansız. Peki bunu neden söylüyorum? Maliyetli geliyorsa, bence bu tam olarak ephemeral agent altyapısına geçmek için doğru motivasyon.
Azure Artifacts upstream feed gerçekten korur mu?
Kendi deneyimimden konuşuyorum, Tam koruma değil ama önemli bir katman (kendi tecrübem). Bir paket bir kez feed’e cache’lendikten sonra public registry’deki değişiklikten etkilenmiyor. Yanı hani siz axios@1.13.0 çekip cache’lediyseniz, public’te ne olursa olsun sizin feed’ınız o temiz versiyonu servis etmeye devam ediyor. Saldırgan yeni bir versiyon yayınlasa bile siz manuel terfi etmediğiniz sürece dokunamıyor.
npm yerine pnpm veya yarn kullansam fark eder mi?
Postinstall script’ler tüm package manager’larda var, yanı teknik olarak hepsi aynı saldırıya açık. Ama pnpm’in daha sıkı izolasyon modelleri var; yarn 2+’da plug-and-play modu da daha öngörülebilir davranıyor. Sihirli çözüm değil, marjinal bir iyileştirme sağlayabilir belki. Tecrübeme göre asıl korunma yine de ignore-scripts ve dependency pinning’de.
Kaynaklar ve İleri Okuma
Şahsen, Axios npm Supply Chain Compromise – Azure Pipelines Resmî Rehberi (Microsoft DevBlogs)
Microsoft-hosted agents for Azure Pipelines (Microsoft Learn)
Azure Pipelines Agents Genel Bakış (Microsoft Learn)
npm Configuration ve.npmrc Dokümantasyonu
Bu içerik işinize yaradı mı?
Benzer içerikleri kaçırmamak için beni sosyal medyada takip edin.



