
Yakın zamanda yazılım paketlerinin yönetiminin, kurumlarda sürekliliğe etkisinden bahsetmiştim. NPM, Javascript için kullanılan bir paket yöneticisi. Bugüne kadar belki de diğer tüm paket yöneticilerinden daha fazla sorun yaşadı.
Bir paket yöneticisi yazılım parçaları kurabilir, onları yeni sürümlerine güncelleyebilir ya da toptan kaldırabilir. Bu nedenle güvenliğine en çok dikkat edilmesi gereken araçlardan biridir. Çünkü onunla ilgili bir güvenlik sorunu yaşadığınız anda, o paket yöneticisinin ilgilendiği tüm yapı (işletim sistemi, belirli bir dilde çalışan yazılım vs) riskli hale gelir.
Tüm paket yöneticileri, güvenlik sorunu yaşamamak için belirli pratikleri uygularlar. Örneğin, merkezi bir paket deposu olur, tüm istemciler yazılımları oradan alarak kurar ve güncellerler. Paket depolarının, sorumluları ve güncelleme politikaları olur. Genellikle her paketin bir paketçisi olur. Hesabına ancak iki faktörlü doğrulama (2FA) ile girebilir. Sadece bu kişi paketin kaynak dosyalarını güncelleyebilir. Güncellemesine günceller ama bu doğrudan devreye alınmaz. Biri bunu gözden geçirir. Paket, kaynak dosyalarına göre el değmeden otomatik oluşturulur. Sonra test deposuna alınır. Belirli şartları sağladığında da canlıya aktarılır. Tıpkı bir yazılım geliştirme süreci gibi.
Merkezi paket deposu özel/açık (public/private) anahtar yöntemi ile kendini istemciye doğrulatır. İstemcinin yanlışlıkla başka bir paket deposuna gitmesini önlemeyi hedefler. Paketlerin her biri de teker teker imzalanır. İstemci de paketi indirdikten sonra imzayı kontrol eder, paketin yolda değiştirilmediğine emin olur. Tipik güvenlik uygulamaları burada da geçerlidir; tüm yetkiler olabildiğince az kişiye dağılır.
Hemen her paket yöneticisi benzer yapıdadır. Farklı GNU/Linux dağıtımlarının farklı paket yöneticileri (DNF, Apt, Zypper, Pacman, Pisi vs), Java’nın Maven’ı, Ruby’nin GEM’i, PHP’nin Composer’ı ve daha niceleri bu yapıyı uygular. Biri hariç: Javascript dünyasına 2010’da bir kurtarıcı gibi inen NPM. NPM, kendinden önce gelenlerin hepsinden daha iyi bildiği için farklı bir yol seçti. NPM istemcisi, bir yazılımın hangi Javascript paketlerine ihtiyaç duyduğu bilgisini okuduğunda, her bir yazılım parçasını, o yazılım parçasını yazan kişinin belirttiği bir Git deposundan doğrudan indirerek çalışacak şekilde tasarlandı.
İlk kez 2012’de bir müşterimizde işletilecek bir Node.js servisi için NPM’le yakından tanışmıştım. Bu tasarımı okuduğumda şaşkına dönmüştüm. Yanlış anlamadığıma emin olmak için, şirketteki diğer deneyimli meslektaşlarımla “akıl sağlığı kontrolü” (sanity check) yapmam gerekmişti. Hatta bir Javascript geliştiricisine de danıştığımı hatırlıyorum.
Yani, NPM’de her bir yazılım paketini, o paketle ilgilenen kişi, hiçbir kontrolden geçmeden güncelleyebiliyor ve bu anında etkin oluyor. Paketi o saniyeden itibaren dünya üzerinde çekecek herkes bu yeni sürümü çekiyor. O kişi bir şekilde kendi güvenlik anahtarını kaptırsa, birileri bu paket üzerinde hemen etkin olacak değişiklikler yapabilir. Aynı zamanda o yazılım parçasının, o Git deposu dışında başka hiçbir yerde kopyası yok demektir. NPM’de milyonlarca paket olduğu düşünülürse, her birinin kendi paketçileri, kendi depoları, kendi güvenlik anlayışları ile milyonlarca saldırı vektörü demekti bu. Saatli bomba gibi. İlk işimiz yazılımın tüm ihtiyaç duyduğu NPM modüllerini toplu halde ayrıca paketleyip sürümlendirmek ve bu paketi kurumun kendi sunucularına yerleştirmek olmuştu.
İlk kan, hem de bir Türk geliştirici tarafından döküldüğü için zamanında ülkemizde çok ses getirmişti. 2016’da ilgili geliştirici, hizmet verdiği bir müşteri ile anlaşmazlığa düşmüştü. Bunun üzerine kendi yönetimindeki Javascript parçasının paket deposunu kaldıran geliştirici, müşterisinin yanı sıra aralarında Netflix, Spotify ve Paypal’ın da olduğu birçok sistemde aksamaya yol açmıştı. O milyonlardan birinin canının sıkılması yetmişti. NPM yöneticileri depoyu geri yerleştirdiler, çözümler yayınladılar, bazı önlemler aldılar. İlk demek son demek değildi tabii.
2022 yılında, yani daha birkaç yıl önce, bir geliştirici (o milyonlarca paket oluşturandan biri), Rusya’nın Ukrayna’yı işgali üzerine, kendi yazılım parçası içine şöyle bir kod yerleştirdi: “Sunucunun IP’sini kontrol et, eğer Rusya ya da onu destekleyen Belarus’a atanan IP bloklarından biriyse, sunucunun diskindeki verileri sil”. Bu hareketle birçok sunucu formatlandı. Olayın asıl duyulması ve fark edilmesiyse, ABD’deki bir kurumun istihbarat amaçlı Rusya’da çalışan sunucularının da bu eylemden nasibini almasıyla oldu. Düşünsenize, yarın biri aynısını Türkiye’ye kayıtlı IP’lerde çalışan bilgisayarlar için de yapabilir. Bu kadar kişi arasında sadece birinin kendini bu konuda haklı görmesi yeterli.
Bulunduğumuz 2025’in son birkaç ayı ise NPM için bir kabus gibiydi. 18 paketçi oltalama (phishing) saldırıları ile erişim bilgilerini çaldırdı. Onların paketlerinden birini sistemlerine kuranların transfer ettikleri kripto paralar, hedeflerini şaşırarak, gönderdikleri kişiler yerine saldırganların hesaplarına gitti. Hemen arkasından 187 NPM paketinde, kuruldukları sistemdeki Github erişim bilgilerini çalan kod parçaları ortaya çıktı. Son bomba ise, 150 bin NPM paketinden birini kuranların sistemlerinin, bir blokzincir token çiftliğine çalışmaya başlaması oldu.
Neden hep NPM? Sırf baştan kendilerinden daha önce onlarca benzer aracın temel pratiklerini NPM’e uygulamadıkları için.
Javascript dünyası zaman içinde NPM’in yerine PNPM, YARN, BUN gibi alternatifler üretmeye çalıştı. O alternatifler de ya (henüz) yeterince yaygınlaşamadılar ya da NPM’in tüm sorunlarına derman olamadılar.
Kurumlarında Javascript uygulamalarını işletmekten sorumlu insanlar, daha uzun süre karın ağrısı yaşayacak görünüyor.