Arka plan
Son zamanlarda MistEye güvenlik izleme sistemi, Red Hat Cloud Services organizasyonu altında yer alan birçok npm paketinde anormal sürümler olduğunu tespit etti. Bu olay, organizasyonun 32 npm paketini ve 96 sürümünü kapsıyor. Bu makalede, 3 yerel örnek derinlemesine çevrimdışı analiz için seçilmiştir: Bu örnekler, taklit edilmiş bir isim uzayı veya tipografik hata kuyruğu paketleri değildir; @redhat-cloud-services kapsamına sahip gerçek paket sürümleridir; örnek kaynak kodlarından, kurulum aşamasında otomatik olarak tetiklenecek çok katmanlı karıştırılmış kötü amaçlı bir yükleyicinin tarball içine yerleştirildiği doğrulanmıştır.
Tam olarak geri yükledikten sonra, bu 3 örneğin temel yükünün GitHub Actions Runner belleğinden okuma, çok bulutlu ve yerel kimlik bilgileri toplama, GitHub API üzerinden dışa aktarma ve dead-drop, GitHub workflow enjeksiyonu, npm ile kendi kendini yayma, Claude Code / VS Code / systemd / LaunchAgent kalıcılığı, Harden-Runner / StepSecurity ile mücadele, EDR ve güvenlik ürünleri tespiti gibi kaynak kodu yeteneklerine sahip olduğu doğrulanabilir. Yetenek kapsamı açısından, potansiyel etkilenen nesneler geliştirici makineleri, CI/CD Runner'ları, yapı konteynerleri, GitHub depoları, GitHub Actions workflow'ları, npm yayılma zinciri ve bulut ortamı kimlik bilgilerini içerir; gerçek etki alanı, kurulum günlükleri, depo denetimleri ve platform tarafı telemetri ile birlikte değerlendirilerek doğrulanmalıdır.
Kod yapısı, yayılma yolu ve yetenek kombinasyonu açısından bu zararlı yazılım, Shai-Hulud zararlı yazılımının bir varyantıdır.
MistEye yanıt veriyor
MistEye, SlowMist tarafından özgün olarak geliştirilen, güvenlik izleme ve tehdit bilgisi birleştirme yeteneklerini entegre eden bir Web3 tehdit istihbaratı ve dinamik güvenlik izleme sistemidir ve kullanıcılara gerçek zamanlı risk uyarıları ve varlık koruması sağlar.
Red Hat Cloud Services npm paketi tedarik zinciri zehirleme olayı ve ilişkili kötü amaçlı örnekler tespit edildikten sonra, MistEye sistemi yüksek tehlike uyarısı tetikledi ve bu saldırı zincirinin karmaşık yapısını, yükü çözümlerini, yeteneklerini ve IOC'lerini sistematik olarak analiz etti.
(https://enterprise.misteye.io/threat-intelligence/SM-2026-378450)
Saldırı zinciri genel bakışı
Bu makalenin teknik analiz bölümü, 3 npm tgz örneğinin paketlenmesi, kod çözülmesi ve karıştırma kaldırılması doğrulanması için yerel çevrimdışı statik analize dayanmaktadır.
Bu doğrulama tarafından kapsanan örnekler şunlardır:
@redhat-cloud-services/frontend-components-config
Sürüm: 6.11.3
tgz SHA-256: 0c9c67ec40d5f23efa1ec3470d0ac88b4993ccc0e92be913fc29a337dfc4f060
@redhat-cloud-services/types
Sürüm: 3.6.1
tgz SHA-256: d543bb3cdf1569c2b3d38c8a4081ed746cfe78bf3236c2302704d79ab7fa9558
@redhat-cloud-services/rule-components
Sürüm: 4.7.2
tgz SHA-256: aaf00d06baa3c679b82452c50014e9824b8874e9ca2d150f19095f8de19ba90f
Üç örneğin saldırı giriş noktaları tamamen aynıdır: package.json dosyalarında scripts.preinstall = "node index.js" bulunmaktadır. Bu, geliştirici makinesi veya CI/CD ortamında bu sürümler kurulduğunda, kök dizindeki index.js dosyasının kurulum aşamasında otomatik olarak çalıştırılacağını, kullanıcıların açıkça import etmesi veya iş kodunu çalıştırmaması gerektiğini gösterir.
Üç örnek, aynı temel zararlı yükü paylaşır ancak dış katman parametreleri farklıdır. Yani, üç örnek farklı ROT/Caesar kaydırma değerleri ve AES-GCM anahtar/iv/tag kullanır; bu, dış katman hash, sabit anahtar veya sabit kaydırma temelli statik özelliklerin doğrudan örnekler arasında yeniden kullanılmasını zorlaştırır. Ancak çözümlenmiş Bun çalışma ortamı başlatıcısı ve temel zararlı yükün hash tamamen aynıdır: biri Bun çalışma ortamını hazırlamak için kullanılan bir başlatma yardımcı modülü, diğeri ise gerçek zararlı işlevleri içeren temel yüküdür. Bu makale, ikisini sırasıyla "Bun Çalışma Ortamı Başlatıcısı (kaynak kodu değişken adı _b)" ve "Temel Zararlı Yük (kaynak kodu değişken adı _p)" olarak adlandırır.
Gerçekleştirilen saldırı zinciri şudur:

Teknik analiz
1. Giriş: npm yaşam döngüsü betiklerinin ele geçirilmesi
Üç örnek de package.json'nin preinstall yaşam döngüsü kancası aracılığıyla saldırı zincirini tetikler:
"scripts": {
preinstall: node index.js
}
preinstall, npm kurma aşamasında otomatik olarak yürütülür. Normal ön uç bileşenleri, tür tanımları veya kural bileşen paketleri için kurma aşamasında genellikle kök dizinde büyük bir JavaScript dosyası çalıştırılmaz; bu, en doğrudan istisnai sinyaldir.
Örnek düzeyindeki kanıtlar şunlardır:
@redhat-cloud-services/frontend-components-config@6.11.3
- ana: lib/index.js
- dosya alanı: ["/lib", "/bin"]
- Kök dizin index.js SHA-256: 545a1838c66e1771f58d84a17b3e1841e5eeab91a73f4ccc59c9492450a6d9c0
@redhat-cloud-services/types@3.6.1
- ana: index.d.ts
- dosya alanı: ayarlanmadı
- Kök dizin index.js SHA-256: b86c5ae9e95bd841a595440faa3eb6317441e746f241ae8fd641ab59ed1d1966
@redhat-cloud-services/rule-components@4.7.2
- ana: index.js
- dosya alanı: ayarlanmadı
- Kök dizin index.js SHA-256: 1a30a9abe20bab121aaa75ed040565af14e6cdfb745609ee0e7b94a2d814fb9c
Bu durumda, frontend-components-config@6.11.3 dosya alanı yalnızca "/lib" ve "/bin" olarak tanımlanmıştır, ancak tarball kök dizininde ek bir index.js mevcuttur ve preinstall tarafından çağrılır. Bu istisna yalnızca bu örnekte geçerlidir; types@3.6.1 ve rule-components@4.7.2 dosya alanı tanımlanmamıştır, bu nedenle bu istisna tüm örnekler için genelleştirilmemelidir.
2. Birinci katman: Sayı dizisi + ROT/Caesar harf yerine koyma
Üç örneğin kök dizinindeki index.js dosyaları, tümü büyük tek satırlı JavaScript dosyalarıdır ve yapıları aynıdır; ana içerik try { eval(...) } catch (...) sarmalayıcısından oluşur:
Bu wrapper, önce büyük sayı dizisini String.fromCharCode ile dizeye dönüştürür, ardından dizedeki İngilizce harfler üzerinde ROT/Caesar kaydırması uygular ve son olarak çözümlenmiş sonucu eval ile yürütür. Hata işleme, kurulum başarısız olduğunda belirgin hata açığını azaltmak için yalnızca "wrapper:" önekiyle çıktı verir.
Üç örneğin dış taşıma değeri ve Stage 2 hash şöyledir:
frontend-components-config@6.11.3
index.js boyutu: 4.294.798 bayt
ROT/Caesar shift: 10
Aşama 2 SHA-256: b19c2fd48535c8c40aeb3e627ce92775f33ef9292611767bb1236c238e6f90cc
types@3.6.1
index.js boyutu: 4.135.588 bayt
ROT/Caesar shift: 4
Aşama 2 SHA-256: 9c0425aa6e6d7792ac38d24f3e7245f42fcaa553ddfeb6bd97677017f10c3b75
rule-components@4.7.2
index.js boyutu: 4.294.336 bayt
ROT/Caesar shift: 11
Aşama 2 SHA-256: d590bd375d95e4ac072b7ebc1fc4489bcaf5f20a939e92486267aa398bcf1e5d
3. İkinci Katman: AES-128-GCM ile Bun yönlendiricisinin ve ana yükün şifresi çözülüyor
ROT/Caesar çözüldükten sonra Stage 2 kodu, Node.js crypto.createDecipheriv kullanılarak AES-128-GCM (Advanced Encryption Standard - Galois/Counter Mode) şifresi çözme işlemi gerçekleştirir ve setAuthTag ile kimlik doğrulama etiketi ayarlanır. Şifre çözme hedefi, Bun çalışma ortamı başlatıcısı ve temel zararlı yük olmak üzere iki sonraki bileşendir.
Bun çalışma ortamı başlatıcısı, Bun çalışma ortamını algılamayı, konumlandırmayı veya hazırlamayı sorumlu tutar ve ardından kodların Bun üzerinden yürütülmesini sağlar; temel zararlı yük ise saldırı zincirinin ana bileşenidir ve sonraki kimlik bilgisi toplama, GitHub/npm yayılımı, kalıcılık, koruma karşıtlığı ve gömülmüş kaynakların şifre çözülmesi gibi ana zararlı yetenekleri içerir.
Üç örnek de, bu iki bileşeni şifrelemek için farklı AES-128-GCM anahtarları, başlangıç vektörleri ve kimlik doğrulama etiketleri kullanmıştır; ancak çözüldükten sonra üç Bun çalışma ortamı başlatıcısının SHA-256 değeri ac2a2208e1726e008be6c73dc0872d9bba163319259dff1b62055ac933ca46b6, üç temel zararlı yükün SHA-256 değeri ise 0dc06ecdaa63fe24859cfd955053c23245c536e4733480239d14bebf12688e35'tir. Bu, saldırganın farklı npm paketlerinde dış katman parametrelerini değiştirdiğini, ancak aynı temel zararlı bileşenleri yeniden kullandığını göstermektedir.
Şifresi çözüldükten sonra, Stage 2, temel zararlı yükü /tmp dizinine yazar, ardından Bun ile çalıştırır ve geçici dosyayı siler. Üç örnekten elde edilen gerçek mantık şöyledir:
Bu nedenle, üç örnekte doğrulanabilir geçici dosya kalıbı şudur:
/tmp/p.js
Bun çalışma ortamı başlatıcısı 898 bayt boyutunda ve üç örnek hash tamamen aynı:
ac2a2208e1726e008be6c73dc0872d9bba163319259dff1b62055ac933ca46b6
Bun çalışma ortamı başlatıcısı, child_process.execSync, fs.existsSync, fs.mkdtempSync, fs.chmodSync, os.platform(), os.arch(), getBunPath() gibi mantıkları içerir ve Bun çalışma ortamını bulmak veya hazırlamak için kullanılır. Yani, 2. Aşama, sistemin küresel Bun’u yüklediğini varsaymaz; Bun çalışma zamanı yolu dışında, önce Bun çalışma ortamı başlatıcısını yükler ve ardından getBunPath() aracılığıyla temel zararlı yükü çalıştırmak için Bun’u çağırır.
4. Üçüncü Katman: obfuscator.io dizesi tablosu
Çözümlenen temel zararlı yük, doğrudan okunabilir bir metin JavaScript değil, obfuscator.io tarzı bir dizi tablosu karmaştırması ile daha da karıştırılmıştır. Bu katman, büyük miktarda dizeyi bir diziye toplar ve çalışma zamanı indeksleme ve döndürme mantığıyla geri çevirir; bu nedenle analistler, dizi tablosunu tamamen çözmedikçe sonraki kritik API'leri, yolları ve yapılandırma adlarını doğrudan alamazlar.
5. Dördüncü Katman: B5 Özelleştirilmiş Dize Şifreleme
obfuscator.io dizesi geri dönüştürüldükten sonra, temel zararlı yük hâlâ bir B5 özel dize şifrelemesi içermektedir. Parametreler doğrulanmıştır:
- KDF: PBKDF2 (Password-Based Key Derivation Function 2)
- Hash fonksiyonu: SHA-256
- İterasyon sayısı: 200000
- Anahtar uzunluğu: 32 bayt
- Şifre Çözme Turu: 3
- şifre: ba2c6ddb3672bdd6a611e6850b4f700b52aed3dab2f1b3d5f8c839d4a157a709
- salt: 5b26508dc0f1075a7c0b4d8aa464487e
Şifresi çözüldükten sonra sonuç şudur:
Bu arada, B5 çözüldükten sonra çeşitli kritik açık metin dizeleri görülebilir. Bazı dizelerin orijinal olarak obfuscator.io dizesi tablosunda yer aldığını unutmayın; yalnızca “dize tablosu yerine geçme + B5 çözme” adımları tamamlandığında doğrudan grep edilebilir:
6. Ek gömme katmanı: AES-256-GCM + gzip
Ana zararlı yükün içinde AES-256-GCM ile şifrelenmiş ve gzip ile sıkıştırılmış gömülü kaynaklar bulunuyor. Geri yükleme mantığı:
Ana gömülü kaynaklar, işlevlerine göre üç kategoriye ayrılmıştır:
Çapraz platform bellek okuma:
Bu tür kaynaklar, çalışan süreçlerin belleğini okumak için kullanılır. Normal dosyalardaki anahtarlar ve tokenlar dosya aramasıyla keşfedilebilir, ancak CI/CD Runner veya geliştirme araçları, bazı hassas değerleri çalışma sırasında bellekte geçici olarak saklar. Saldırganlar, Linux, Windows ve macOS platformları için bellek okuma betikleri yerleştirerek, farklı sistemlerde süreç belleğinden bu geçici olarak ortaya çıkan gizli bilgileri toplamayı amaçlar.

Sabit yapılandırma:
Bu kaynaklar, “arka kapı tetikleme noktası” bırakmak için kullanılır. Yani, ilk npm kurulum süreci tamamlandıktan sonra bile, saldırganlar, geliştiricinin projeyi daha sonra açması, düzenleyiciyi başlatması, Claude Code oturumuna girmesi veya sistem yeniden oturum açtığında kötü amaçlı kodun yeniden çalışmasını ister. Bu nedenle bu kaynaklar, proje düzeyi yapılandırmayı ve kullanıcı düzeyi otomatik başlatma mekanizmalarını hedefler: proje düzeyi yapılandırmalar daha gizli, sistem düzeyi hizmetler ise uzun vadeli çalışmak için daha uygundur.

C2 ve Yayılım:
Bu gömülü kaynaklar, sonraki kontrol zinciri ve deposu gizlilik anahtarlarının taşınması için kullanılır. YZ, çözüldüğünde GitHub commit arama izleyicisi olur ve periyodik olarak firedalazer . formatındaki commit mesajlarını arar, imzayı doğruladıktan sonra uzaktaki Python içeriğini indirir ve çalıştırır; zZ, çözüldüğünde "Run Copilot" adlı bir GitHub Actions iş akışı şablonudur ve ${{ toJSON(secrets) }} değerini format-results.txt dosyasına yazar ve bir artifact olarak yükler. İlkisi, sonraki görevlerin alınması/çalıştırılması zincirini sağlar, ikincisi ise GitHub Actions artifact aracılığıyla deposu gizlilik anahtarlarının taşınması için bir şablon sunar; gerçek iş akışı enjeksiyonu, çalıştırma bekleme ve artifact indirme işlemleri, ana yükün eşlik eden GitHub API mantığı tarafından tamamlanır.

Ana zararlı yük yetenekleri analizi
Çok katmanlı karmaşıklaştırma tamamlandıktan sonra örnek, nihayetinde temel zararlı yükü serbest bırakır ve çalıştırır. Aşağıdaki tüm analizler, temel zararlı yük modülüne odaklanarak, veri toplama, dışa aktarma, yayılma, kalıcılık ve karşılaşma olmak üzere beş aşamada ayrı ayrı incelenmiştir.
1. GitHub Actions Runner bellek okuması:
Örnek, Linux, Windows ve macOS platformları için bellek okuma betiklerini içerir ve çapraz platform dump yeteneğine sahiptir. Linux uygulaması, hedef işlem için /proc//maps ve /proc//mem dosyalarını okuyarak bellek çıkarımını gerçekleştirir:
GitHub Actions Linux runner üzerinde aktif tetikleme mantığı: GITHUB_ACTIONS === "true" ve RUNNER_OS === "Linux" olduğunda, kod Runner.Worker sürecini arar ve belleğini çıkarır; ardından çıkarılan veriden "":{"value":"","isSecret":true} formatındaki maskelenmiş gizli anahtarları alır. Üç örnekte de aktif toplama yollarının Linux runner odaklı olduğu doğrulanmıştır, ancak üç platformun scriptleri de dahil edilmiştir.
2. Bulut ve geliştirici yerel kimlik bilgileri toplama:
Ana zararlı yük, bulut sağlayıcıları, CI ortamları, geliştirici yerel yapılandırmaları, GitHub CLI, şifre yöneticileri ve cüzdan dosyalarını kapsayan sistemli kimlik bilgisi toplama modüllerini içerir.
Bulut sağlayıcı kimlik bilgileri toplama hedefleri şunlardır:

AWS modülü, ECS/IMDS (Örnek Meta Veri Hizmeti)/STS WebKimlik ilgili mantığı da içerir.
Geliştirici yerel kimlik bilgileri toplama şu hedefleri kapsar:

Şifre yöneticisi mantığı, shell dizgi birleştirme yerine kaynak kodunda runCommand(command, args) dizisi şeklinde uygulanmıştır.
Yukarıdaki kimlik bilgisi toplama modülü, bulut platformundan geliştiricinin yerel sistemine kadar geniş bir hedef kapsamlıdır; toplanan hassas veriler aşağıdaki mekanizmalarla dışarıya aktarılır.
3. GitHub API sızıntısı ve dead-drop:
Ana zararlı yük, GitHub API'sini ana veri dışa aktarma kanalı olarak kullanır. İstekler, User-Agent olarak python-requests/2.31.0 olarak sahtelenir ve x-oauth-scopes token doğrulaması (repo, public_repo veya workflow içermelidir) yapıldıktan sonra dışa aktarma işlemi gerçekleştirilir: repository oluşturulur (description sabit olarak Miasma: The Spreading Blight), çalınan veriler base64 ile kodlandıktan sonra PUT /repos///contents/results/ üzerinden yazılır.
Ayrıca, yük, GitHub commit aramasına dayalı bir dead-drop mekanizması gerçekleştirmiş olup, "thebeautifulmarchoftime" (veya "thebeautifulsnadsoftime") işareti aranarak C2 komutları alınmaktadır:
let result = await X9("thebeautifulmarchoftime ", xZ);
YZ.bin gömülü kaynağı, 3600 saniye aralıklarla firedalazer . formatındaki commit mesajlarını aramak için bağımsız bir GitHub commit izleyicisidir; imza doğrulamasından sonra uzaktaki Python içeriği indirilir ve çalıştırılır. Bu, ana dış kanaldan bağımsız bir takip kontrol bağlantısı oluşturur.
Kaynak kodunda, api.anthropic.com ve v1/api hedef uç noktalarına yönelik bir HTTP POST gönderici yapılandırması da yer almaktadır. Bu yapılandırmanın noop alanı true olarak ayarlanmıştır, bu da dışarıdan değiştirilmediği sürece bu göndericinin gerçek bir ağ isteği başlatmayacağını anlamına gelir. Bu nedenle statik analiz, yalnızca bu kod yapısının varlığını doğrulayabilir, aktif bir Anthropic API dış veri sızıntısı olduğunu kanıtlayamaz.
4. GitHub deposu ve iş akışı bulaşması:
Ana zararlı yük, GitHub REST / GraphQL API'si aracılığıyla depo git nesnelerini işlemeye izin verir:

Release adıyla yüklenen zararlı workflow, OIDC (OpenID Connect) yoluyla npm yayımlama jetonu elde etmek için id-token: write izni talep eder. OIDC yolu için ortam değişkenleri ve API, ACTIONS_ID_TOKEN_REQUEST_TOKEN ve ACTIONS_ID_TOKEN_REQUEST_URL olup, audience npm:registry.npmjs.org olarak ayarlanır. Kaynak kod düzeyinde, payload'un GitHub deposuna workflow eklemek ve OIDC/npm güvenilir yayınlama yoluyla yayımlama izni elde etme yeteneği doğrulanmıştır.
Yukarıda belirtilen git refs aracılığıyla workflow'ya yüklenen yöntemlerin dışında, yük, Run Copilot olarak görünmesini sağlayan daha gizli bir gizli anahtar taşıma mekanizması da içerir: ${{ toJSON(secrets) }} ifadesi format-results.txt dosyasına yazılır ve artifact olarak yüklenir. Gizli anahtarların doğrudan deposunun içine yazılmasıyla karşılaştırıldığında, bu yöntem, workflow çalıştırma çıktıları aracılığıyla veri taşımaya daha çok odaklanır ve düzenli kod diff incelemeleri son olarak dışa aktarılan gizli anahtar içeriklerini doğrudan göremeyebilir.
5. Copilot iş akışını artifact aracılığıyla gizlilikleri taşıyın:
zZ.bin dosyası, Copilot gibi görünen bir GitHub Actions iş akışıdır ve ${{ toJSON(secrets) }} verisini format-results.txt dosyasına yazar ve bir artifact olarak yükler.
İlgili GitHub API davranışları şunları içerir: geçici branch oluşturma/güncelleme → workflow blob yazma → workflow çalışmasını bekleme → artifact zip dosyasını indirme → format-results.txt okuma → workflow çalışmasını ve geçici branch’i silme. İlgili arama anahtar kelimeleri: Run Copilot, VARIABLE_STORE, format-results, chore/add-codeql-static-analysis, .github/workflows/codeql.yml.
6. npm kendi kendini yayma:
Ana zararlı yükün iki bağımsız npm yayınlama / yayılma yolu vardır.
npm token yolu: GET /-/npm/v1/tokens üzerinden geçerli kullanıcının npm token'larını listeleme, bypass_2fa === true ve paket yazma iznine sahip token'ları filtreleme; bu token'larla otomatik yayın gerçekleştirme. bypass_2fa, token meta veri alanıdır, publish gövde parametresi değildir.
GitHub Actions OIDC yolu: Yüklemeyi okumak için ACTIONS_ID_TOKEN_REQUEST_TOKEN ve ACTIONS_ID_TOKEN_REQUEST_URL ortam değişkenlerini kullanın, audience olarak npm:registry.npmjs.org olan bir OIDC belirteci isteyin ve npm OIDC belirteç değişimi arayüzünü kullanarak yayıncı izinleri edinin.
Kirlenmiş hedef tarball işlemini açma → zararlı index.js yazma → package.json değiştirme:
İki tür giriş noktası ayrılır: Üç yerel yükleme örneği, preinstall: "node index.js" ile kendilerini kullanır—bu durumda ortam kurulumu için Bun önceden yüklenmeye gerek yoktur, Node.js ile başlangıç daha gizli olur; Kendini yayarken diğer paketlere bulaştırmak için preinstall: "bun run index.js" yazılır ve Bun bağımlılığı eklenir—çünkü temel zararlı yükün sonraki mantığı, Bun çalışma zamanının sağladığı API’lere (Bun.gunzipSync ve Bun.file gibi) dayanır; Kendini yayma senaryolarında hedef ortamın Bun’u zaten sahip olduğundan emin olunmalıdır.
7. Kalıcılık mekanizması:
Ana zararlı yük, proje dizini ve sistem düzeyi otomatik başlatma için dört kalıcı yöntem içerir.
Claude Code Oturumu Başlatma kancası: S8.bin kaynağını .claude/settings.json dosyasına yerleştirerek, her Claude Code oturumu başlatıldığında otomatik olarak node .claude/setup.mjs çalıştırır. Zararlı yük, aynı zamanda .claude/setup.mjs ve .claude/index.js dosyalarına yazılır (yol, ".claude/" + M0 ile birleştirilir; M0 = "index.js").
VS Code klasörAç görevi: EZ.bin kaynak dosyasını, klasörAç görevini .vscode/tasks.json dosyasına yazarak, enfekte edilen proje klasörünü açtığınızda aynı betiği otomatik olarak çalıştırır. Aynı zamanda .vscode/setup.mjs dosyasına da yazar.
kitty-monitor (systemd / LaunchAgent): RZ.bin kaynaklarını gömmek suretiyle kalıcı bir hizmet kurar; dosyalar /.local/share/kitty/cat.py, /.config/systemd/user/kitty-monitor.service (Linux) ve ~/Library/LaunchAgents/com.user.kitty-monitor.plist (macOS) konumlarında dağıtılmıştır. Zararlı yük, /tmp/kitty- dizinini oluşturur, YZ.bin'i (GitHub commit izleyici) cat.py içine yazar ve RZ.bin aracılığıyla kurar.
gh-token-monitor (systemd / LaunchAgent): jZ.bin kaynak dosyasını kullanarak GitHub token izleme hizmetini kurar; dosyalar /.local/bin/gh-token-monitor.sh, /.config/gh-token-monitor/ dizinleri ve ilgili systemd / LaunchAgent yollarına dağıtılmıştır. Bu izleyici, GitHub token'ının 40x durum kodu döndürüp dönmediğini ve npm paketi @cap-js/openapi@1.4.1'in meta verilerinin anomali gösterip göstermediğini kontrol eder; tetiklendiğinde handler'ı çalıştırır:
Bu, monitor'un GitHub API'den 40x durum kodu aldığında, örneğin token iptal edilmiş, geçersiz hale gelmiş veya izin durumu anormal olduğunda, gelen handler'in çalıştırıldığı anlamına gelir. Bu makaledeki üç örnekten geri kazanılan handler, rm -rf ~/; rm -rf ~/Documents şeklindedir. İşlem sırasında, payload hâlâ çalışan bir ana makinede doğrudan token'i iptal etmeyin—önce ana makineyi izole edin, kalıcı öğeleri ve çalışan süreçleri temizleyin, ardından temiz bir ortamdan kimlik bilgilerini değiştirin.
8. Harden-Runner / StepSecurity Mücadelesi:
Çekirdek zararlı yük, StepSecurity Harden-Runner için tespit ve imha mantığı içerir ve CI/CD korumalarını aşağıdaki adımlarla atlar:
- Docker soketinin /var/run/docker.sock kullanılıp kullanılmadığını kontrol edin;
- Docker konteynerlerini listeleyin, adında veya görüntüsünde harden-runner / stepsecurity anahtar kelimelerini eşleştirin;
- Eşleşen konteyneri POST /containers//kill ile durdurun;
- Özel alpine konteyneri oluşturun, sudoers dosyasını runner ALL=(ALL) NOPASSWD:ALL olarak değiştirin;
- /etc/hosts dosyasına StepSecurity ile ilgili alan adları için geçersiz bir çözüm yazın;
- /etc/resolv.conf dosyasını 8.8.8.8 ve 1.1.1.1 ile değiştirin.
Bu saldırı mantığı, örneğin StepSecurity ile korunan CI/CD ortamlarına özel olarak uyarlandığını göstermektedir.
9. EDR / Güvenlik ürünü tespiti, ortam analizi ve kaçınılması:
Ana zararlı yük, çeşitli EDR (Endpoint Detection and Response) / güvenlik ürünlerinin işlem adlarını ve kurulum yollarını tespit eder:

Yük, LC_ALL, LC_MESSAGES, LANGUAGE, LANG çevre değişkenlerini algılar, küçük harfe dönüştürüldükten sonra ru ile başlıyorsa yürütümü atlar. CI ortamı tanımı, GitHub Actions, GitLab CI, Travis CI, CircleCI, Jenkins, AWS CodeBuild, Buildkite, AppVeyor, Bitbucket, Drone, TeamCity, Cirrus CI gibi platformları destekler. Çalışma zamanı durum işaretleyicileri arasında tmp.0987654321.lock, __IS_DAEMON (ayrık daemon alt işlemi için işaret), SKIP_DOMAIN (domain gönderici yolu atla), /tmp/kitty-*, cat.py ve /var/tmp/.gh_update_state yer alır.
Etki analizi
Kaynak kodu yeteneklerine göre, bu üç örneğin etkisi, npm kurma aşamasındaki tek seferlik yürütmeyle sınırlı değildir. Gerçek riskleri dört katmanda ayrılabilir:
Geliştirici ana bilgisayar seviyesinde. Örnekler, ortam değişkenlerini, .npmrc'yi, .pypirc'yi, SSH anahtarını, Docker yapılandırmasını, .env dosyasını, GitHub CLI jetonunu, şifre yöneticisi verilerini ve cüzdan dosyalarını toplar ve Claude Code, VS Code, systemd kullanıcı servisi veya macOS LaunchAgent aracılığıyla sonraki tetiklemeleri sağlar.
CI/CD Runner düzeyinde. Örnek, GitHub Actions Linux runner'ı tanımlar, Runner.Worker işlem belleğini okur ve maskelenmiş gizlilikleri çıkarır; aynı zamanda StepSecurity Harden-Runner karşıtı mantığa sahiptir ve CI/CD koruma bileşenlerini bozmaya veya atlamaya çalışır.
GitHub organizasyon ve deposu düzeyinde. Örnekler, GitHub API kullanarak depo oluşturabilir, contents/results/ içeriğini yazabilir, git refs/blobs/trees/commits işlemlerini gerçekleştirebilir, zararlı workflow ekleyebilir ve Run Copilot workflow + artifact ile gizli anahtarları taşıyabilir.
npm ekosistemi yayılma düzeyi. Örnekler, package yazma iznine sahip ve bypass_2fa === true olan npm belirteçleriyle seçilebilir; ayrıca GitHub Actions OIDC / npm güvenilen yayınlama yoluyla yayınlama yetkisi elde edilebilir; ardından hedef tarball indirilir, zararlı bir yükleyici eklenir, preinstall değiştirilir, Bun bağımlılığı eklenir, patch sürümü yükseltilir ve yayımlanır, böylece npm içinde kendi kendini yayılan bir zincir oluşturulur.
Özet
Üç örnek kod kanıtı, bu zararlı paketin basit bir kurulum aşaması veri çalma betiği olmadığını, bunun yerine çok aşamalı bir yükleyici ve tam bir implanta sahip olduğunu göstermektedir: dış katman pakete göre rastgeleleştirilmiştir, Bun çalışma ortamı başlatıcısı ve çekirdek zararlı yükü tutarlıdır; ana implant, kimlik bilgisi toplama, CI gizliliklerinin çıkarılması, GitHub/npm yayılımı, kalıcılık ve koruma karşıtlığı gibi birçok aşamayı kapsar.
Yüksek gizlilikli giriş tasarımı. Saldırganlar, kötü amaçlı kodu iş koduna yerleştirmek yerine npm yaşam döngüsü betiklerine karıştırılmış bir yükleyici ekler. Bu yükleyici, gömülü yükü çözerek çalıştırmaktan sorumludur ve bu da gerçek yeteneklerin yalnızca iş kaynak kodu incelemesiyle tespit edilmesini zorlaştırır.
Çok katmanlı iç içe geçmiş karmaşık zincir. Zararlı yük, sayı dizisi + ROT harf yerine koyma, AES-128-GCM şifreleme, obfuscator.io karmaşıklaştırma, B5 özgün dize şifreleme ve AES-256-GCM + gzip iç içe katmanları olmak üzere beş katmanla sarılmıştır. Her katmandaki anahtar veya parametreler farklı paketlerde bağımsız olarak değişebilir, bu da statik özelliklere dayalı toplu tespiti daha zor hale getirir.
Tam organizasyonel seviyede bir saldırı yeteneği. Bu implant, GitHub Actions Runner belleğinin okunmasını, çok bulutlu ve yerel kimlik bilgilerinin toplanmasını, GitHub API aracılığıyla veri dışa aktarma ve dead-drop yöntemlerini, GitHub depoları ve workflow’ların bulaştırılmasını, npm üzerinden kendini çoğaltmayı, kalıcılığı ve koruma önlemlerine karşı mücadele etmeyi sağlar. Kaynak kod yapısına göre, tek bir noktadan kurulumun depolar, CI/CD ve npm yayınlama zincirine yayılmasını tetikleyecek kod yollarına sahiptir; gerçek yayılma ölçeği, kurulum günlükleri, depo denetimleri ve platform tarafı telemetri verileriyle doğrulanmalıdır.
Kaynak kodu kanıtlarına göre, üç örnek de preinstall aracılığıyla otomatik olarak tetiklenerek aynı ana implant'i çözüp çalıştırmaktadır. Ancak gerçek olayda ilk erişim nasıl elde edildiği, bu üç tgz örneğiyle kanıtlanamaz.
Önerilen işlem
- Proje bağımlılıklarında, lockfile'da, özel registry önbelleğinde ve build önbelleğinde kötü amaçlı sürümleri tespit edin ve kaldırın.
- Yükleme günlüklerinde preinstall, node index.js, bun run, /tmp/p*.js, tmp.0987654321.lock ifadelerinin olup olmadığını kontrol edin.
- Hala payload çalıştırma ihtimali olan kurban makinesinde doğrudan token'i iptal etmeyin. Önerilen yöntem, kurban makinesini izole etmek, çalışan süreçleri ve kalıcı öğeleri temizlemek, ardından temiz bir ortamdan GitHub, npm, bulut kimlik bilgileri, Kubernetes, Vault, SSH, Docker registry ve şifre yöneticisi ile ilgili token'leri değiştirmektir.
- GitHub deposunun son branch'ini, commit'ini, workflow'ını, artifact'ını ve yeni oluşturulan deposunu kontrol edin; Run Copilot, format-results, chore/add-codeql-static-analysis, .github/workflows/codeql.yml, OIDC_PACKAGES gibi anahtar kelimelere odaklanın.
- Proje dizininde yeni dosyalar eklenmiş mi veya mevcut dosyalar değiştirilmiş mi kontrol edin: .claude/settings.json, .claude/setup.mjs, .vscode/tasks.json, .vscode/setup.mjs.
- Kullanıcı düzeyi kalıcılığını kontrol edin: /.local/share/kitty/cat.py, /.config/systemd/user/kitty-monitor.service, ~/Library/LaunchAgents/com.user.kitty-monitor.plist, gh-token-monitor ilgili dosyalar.
- npm yayımlama geçmişini kontrol edin ve yetkisiz patch sürüm yayınlamalarının olup olmadığını doğrulayın; aynı zamanda npm token meta verilerini denetleyin ve 2FA (İki Aşamalı Doğrulama) atlanabilen ve paket yazma iznine sahip tokenlara odaklanın.
- Kirlenmiş ortamlarda oluşturulan alt ürünleri bütünlük denetimine tabi tutun.
IOC
Kötü niyetli dosya
dosya adı: redhat-cloud-services-frontend-components-config-6.11.3.tgz MD5: 633ad8849a59e2bfb7a0fe589e816a07 SHA1: 675294612f455fe6a9acb195f0cbe3687d8e2e34 SHA256: 0c9c67ec40d5f23efa1ec3470d0ac88b4993ccc0e92be913fc29a337dfc4f060
dosya adı: redhat-cloud-services-types-3.6.1.tgz MD5: 9e6c5af01438b52c9a411686c1f1b8ff SHA1: 88d098c8d96e9ae17550e9798c3b62c420464b8c SHA256: d543bb3cdf1569c2b3d38c8a4081ed746cfe78bf3236c2302704d79ab7fa9558
dosya adı: redhat-cloud-services-rule-components-4.7.2.tgz MD5: f1ffdbf5e639899f26a6ebab2eec408d SHA1: f3c5c21274045ae02fef11e931de6dcf8462a067 SHA256: aaf00d06baa3c679b82452c50014e9824b8874e9ca2d150f19095f8de19ba90f
SHA256
ac2a2208e1726e008be6c73dc0872d9bba163319259dff1b62055ac933ca46b6
0dc06ecdaa63fe24859cfd955053c23245c536e4733480239d14bebf12688e35
Kötü niyetli bağımlılık
npm:@redhat-cloud-services/topological-inventory-client@3.0.10
npm:@redhat-cloud-services/topological-inventory-client@3.0.11
npm:@redhat-cloud-services/topological-inventory-client@3.0.13
npm:@redhat-cloud-services/compliance-client@4.0.3
npm:@redhat-cloud-services/compliance-client@4.0.4
npm:@redhat-cloud-services/compliance-client@4.0.6
npm:@redhat-cloud-services/rbac-client@9.0.3
npm:@redhat-cloud-services/rbac-client@9.0.4
npm:@redhat-cloud-services/rbac-client@9.0.6
npm:@redhat-cloud-services/insights-client@4.0.4
npm:@redhat-cloud-services/insights-client@4.0.5
npm:@redhat-cloud-services/insights-client@4.0.7
npm:@redhat-cloud-services/frontend-components@7.7.2
npm:@redhat-cloud-services/frontend-components@7.7.3
npm:@redhat-cloud-services/frontend-components@7.7.5
npm:@redhat-cloud-services/frontend-components-utilities@7.4.1
npm:@redhat-cloud-services/frontend-components-utilities@7.4.2
npm:@redhat-cloud-services/frontend-components-utilities@7.4.4
npm:@redhat-cloud-services/remediations-client@4.0.4
npm:@redhat-cloud-services/remediations-client@4.0.5
npm:@redhat-cloud-services/remediations-client@4.0.7
npm:@redhat-cloud-services/frontend-components-notifications@6.9.2
npm:@redhat-cloud-services/frontend-components-notifications@6.9.3
npm:@redhat-cloud-services/frontend-components-notifications@6.9.5
npm:@redhat-cloud-services/patch-client@4.0.4
npm:@redhat-cloud-services/patch-client@4.0.5
npm:@redhat-cloud-services/patch-client@4.0.7
npm:@redhat-cloud-services/host-inventory-client@5.0.3
npm:@redhat-cloud-services/host-inventory-client@5.0.4
npm:@redhat-cloud-services/host-inventory-client@5.0.6
npm:@redhat-cloud-services/rule-components@4.7.2
npm:@redhat-cloud-services/rule-components@4.7.3
npm:@redhat-cloud-services/rule-components@4.7.5
npm:@redhat-cloud-services/frontend-components-advisor-components@3.8.2
npm:@redhat-cloud-services/frontend-components-advisor-components@3.8.4
npm:@redhat-cloud-services/frontend-components-advisor-components@3.8.6
npm:@redhat-cloud-services/notifications-client@6.1.4
npm:@redhat-cloud-services/notifications-client@6.1.5
npm:@redhat-cloud-services/notifications-client@6.1.7
npm:@redhat-cloud-services/sources-client@3.0.10
npm:@redhat-cloud-services/sources-client@3.0.11
npm:@redhat-cloud-services/sources-client@3.0.13
npm:@redhat-cloud-services/integrations-client@6.0.4
npm:@redhat-cloud-services/integrations-client@6.0.5
npm:@redhat-cloud-services/integrations-client@6.0.7
npm:@redhat-cloud-services/frontend-components-config@6.11.3
npm:@redhat-cloud-services/frontend-components-config@6.11.4
npm:@redhat-cloud-services/frontend-components-config@6.11.6
npm:@redhat-cloud-services/frontend-components-config-utilities@4.11.2
npm:@redhat-cloud-services/frontend-components-config-utilities@4.11.3
npm:@redhat-cloud-services/frontend-components-config-utilities@4.11.5
npm:@redhat-cloud-services/hcc-pf-mcp@0.6.1
npm:@redhat-cloud-services/hcc-pf-mcp@0.6.2
npm:@redhat-cloud-services/hcc-pf-mcp@0.6.4
npm:@redhat-cloud-services/frontend-components-remediations@4.9.2
npm:@redhat-cloud-services/frontend-components-remediations@4.9.3
npm:@redhat-cloud-services/frontend-components-remediations@4.9.5
npm:@redhat-cloud-services/eslint-config-redhat-cloud-services@3.2.1
npm:@redhat-cloud-services/eslint-config-redhat-cloud-services@3.2.2
npm:@redhat-cloud-services/eslint-config-redhat-cloud-services@3.2.4
npm:@redhat-cloud-services/javascript-clients-shared@2.0.8
npm:@redhat-cloud-services/javascript-clients-shared@2.0.9
npm:@redhat-cloud-services/javascript-clients-shared@2.0.11
npm:@redhat-cloud-services/quickstarts-client@4.0.11
npm:@redhat-cloud-services/quickstarts-client@4.0.12
npm:@redhat-cloud-services/quickstarts-client@4.0.14
npm:@redhat-cloud-services/config-manager-client@5.0.4
npm:@redhat-cloud-services/config-manager-client@5.0.5
npm:@redhat-cloud-services/config-manager-client@5.0.7
npm:@redhat-cloud-services/hcc-feo-mcp@0.3.1
npm:@redhat-cloud-services/hcc-feo-mcp@0.3.2
npm:@redhat-cloud-services/hcc-feo-mcp@0.3.4
npm:@redhat-cloud-services/entitlements-client@4.0.11
npm:@redhat-cloud-services/entitlements-client@4.0.12
npm:@redhat-cloud-services/entitlements-client@4.0.14
npm:@redhat-cloud-services/tsc-transform-imports@1.2.2
npm:@redhat-cloud-services/tsc-transform-imports@1.2.4
npm:@redhat-cloud-services/tsc-transform-imports@1.2.6
npm:@redhat-cloud-services/hcc-kessel-mcp@0.3.1
npm:@redhat-cloud-services/hcc-kessel-mcp@0.3.2
npm:@redhat-cloud-services/hcc-kessel-mcp@0.3.4
npm:@redhat-cloud-services/frontend-components-testing@1.2.1
npm:@redhat-cloud-services/frontend-components-testing@1.2.2
npm:@redhat-cloud-services/frontend-components-testing@1.2.4
npm:@redhat-cloud-services/types@3.6.1
npm:@redhat-cloud-services/types@3.6.2
npm:@redhat-cloud-services/types@3.6.4
npm:@redhat-cloud-services/chrome@2.3.1
npm:@redhat-cloud-services/chrome@2.3.2
npm:@redhat-cloud-services/chrome@2.3.4
npm:@redhat-cloud-services/frontend-components-translations@4.4.1
npm:@redhat-cloud-services/frontend-components-translations@4.4.2
npm:@redhat-cloud-services/frontend-components-translations@4.4.4
npm:@redhat-cloud-services/vulnerabilities-client@2.1.8
npm:@redhat-cloud-services/vulnerabilities-client@2.1.9
npm:@redhat-cloud-services/vulnerabilities-client@2.1.11
