- Sejumlah paket npm yang menyertakan paket open source @ctrl/tinycolor terdampak versi berbahaya; penyebabnya adalah pencurian token npm melalui workflow GitHub Actions di repositori kolaboratif
- Penyerang menggunakan token npm dengan izin luas untuk menyebarkan kode berbahaya ke sekitar 20 paket, dan di antaranya @ctrl/tinycolor memiliki sekitar 2 juta unduhan per minggu sehingga dampaknya besar
- Versi yang terinfeksi menjalankan payload berbahaya pada tahap postinstall, dan tim keamanan GitHub serta npm merespons dengan cepat untuk melakukan penghapusan dan pembersihan
- Penulis menyiapkan rencana keamanan yang diperkuat untuk mencegah kejadian serupa, termasuk migrasi ke Trusted Publishing(OIDC), meminimalkan izin token, mewajibkan 2FA, dan memanfaatkan fitur pnpm
- Insiden ini menunjukkan kerentanan keamanan rantai pasok perangkat lunak dan menjadi contoh yang menegaskan perlunya peningkatan fitur keamanan serta perubahan praktik keamanan di seluruh ekosistem npm
TL;DR
- Sebuah workflow GitHub Actions berbahaya didorong ke repositori bersama dan mencuri token npm
- Dengan token tersebut, penyerang menyebarkan versi berbahaya dari 20 paket, dan @ctrl/tinycolor memiliki dampak besar karena jumlah unduhannya tinggi
- Akun pribadi maupun repositori tidak dibobol secara langsung, dan tidak ada phishing atau pemasangan malware lokal
- Berkat respons cepat tim keamanan GitHub/npm, versi berbahaya dihapus, lalu versi bersih diterbitkan ulang untuk membersihkan cache
Bagaimana insiden ini diketahui (How I Found Out)
- Pada sore hari 15 September, anggota komunitas Wes Todd memberi tahu masalah ini melalui DM Bluesky
- Tim keamanan GitHub/npm sudah lebih dulu menyusun daftar paket yang terdampak dan memulai tindakan penghapusan
- Sebagai petunjuk awal, nama branch berbahaya "Shai-Hulud" dibagikan; nama ini diambil dari sandworm dalam semesta Dune
Apa yang sebenarnya terjadi (What Actually Happened)
- Ada kolaborator yang masih memiliki hak admin di repositori angulartics2 yang pernah dikerjakan bersama sejak lama
- Token npm yang disimpan di repositori tersebut dicuri oleh workflow GitHub Actions berbahaya
- Dengan token ini, penyerang menerbitkan sekitar 20 paket termasuk @ctrl/tinycolor
- Tim keamanan GitHub/npm dengan cepat menghapus versi berbahaya, dan penulis menerbitkan ulang versi baru yang tepercaya
Dampak (Impact)
- Jika memasang versi berbahaya, skrip postinstall akan dijalankan dan menimbulkan ancaman keamanan
- Pengguna yang terdampak disarankan merujuk ke panduan respons segera dari StepSecurity
Lingkungan publikasi dan rencana penanganan (Publishing Setup & Interim Plan)
- Sebelumnya, publikasi otomatis dilakukan dengan kombinasi semantic-release + GitHub Actions
- Fitur npm provenance digunakan, tetapi tidak mampu menghentikan penyerang yang memiliki token valid
- Ke depan, ada rencana mengadopsi Trusted Publishing(OIDC) untuk menghapus token statis
- Saat ini semua token telah dicabut dan langkah keamanan tambahan sedang diterapkan, seperti mewajibkan 2FA, hanya mengizinkan token dengan izin granular, serta meninjau fitur minimumReleaseAge milik pnpm
Usulan perbaikan ideal (Publishing Wishlist)
- Perlu ada opsi untuk memaksa Trusted Publishing berbasis OIDC di tingkat akun npm
- Diperlukan fitur untuk memblokir publikasi saat provenance tidak ada, serta dukungan integrasi penuh semantic-release dengan OIDC
- Diharapkan GitHub UI menyediakan fitur publikasi dengan persetujuan manual berbasis 2FA
- Fitur perlindungan setingkat GitHub Environments seharusnya dapat digunakan tanpa langganan Pro
- Halaman paket npm perlu menampilkan apakah ada skrip postinstall dan mengungkap alasan versi yang dihapus
1 komentar
Komentar Hacker News
Repositori tersebut ternyata masih menyimpan GitHub Actions secret, yaitu token npm dengan hak publikasi yang sangat luas
Salah satu keuntungan Trusted Publishing adalah kita tidak lagi perlu memakai token publikasi jangka panjang
Sekarang yang dipakai hanya token berumur pendek yang dibuat sementara di CI VM, dan token itu hanya berlaku selama 15 menit
Ini sudah diterapkan di berbagai ekosistem seperti PyPI, npm, Cargo, Homebrew, dan lainnya
Bahkan proses rilisnya bisa jadi lebih mudah, jadi saya sarankan semua orang mencobanya
Kalau dokumentasinya masih terasa kurang jelas, silakan minta bantuan kapan saja
Para pengelola ekosistem tampaknya sangat ingin fitur ini diadopsi lebih luas
Lihat dokumentasi resmi Trusted Publishing
Baru kali ini saya tahu bahwa npm sekarang mendukung Trusted Publishing
Kabar terkait
Akhir pekan ini saya berencana langsung menyiapkannya
Akan bagus kalau ada semacam flag di repositori yang menandai bahwa proyek ini memakai fitur seperti ini
Dengan begitu, paket dependensi yang tidak memakainya bisa dengan mudah diblokir
Rasanya poin tentang memasukkan MFA (autentikasi multi-faktor) ke dalam proses deployment otomatis belum cukup mendapat perhatian
Mempublikasikan lewat workflow CI sambil mengonfirmasi rilis lewat prompt MFA sebenarnya tidak masalah, tetapi terakhir kali saya cek prosesnya rumit karena perlu membuka tunnel HTTPS untuk tujuan penyajian kode
Akan bagus kalau npm atau GitHub menyediakan cara bawaan yang mudah untuk memberikan dan mengonfirmasi kode MFA saat CI berjalan
Publikasi paket punya 2 tahap: mengunggah paket ke npmjs, dan tahap benar-benar membukanya untuk pengguna
Saat ini dua tahap itu digabung jadi satu pekerjaan
Menurut saya keduanya sebaiknya dipisahkan, sehingga sistem CI hanya membangun dan mengunggah secara otomatis
Lalu untuk benar-benar merilis paket yang sudah diunggah, seseorang harus login langsung ke situs npmjs dan melakukan publish manual serta MFA
Sebenarnya saya jadi bertanya-tanya apakah konsep publikasi paket itu sendiri memang perlu
Kalau VCS adalah "sumber yang sesungguhnya", kenapa tidak dipakai langsung tanpa proses publish terpisah
Bahasa Go memang melakukan ini
Paket di-import langsung berdasarkan URL dan versioning dikelola lewat tag
Dengan begitu kita hanya perlu mempercayai VCS sehingga permukaan serangan tambahan berkurang
Tidak perlu membandingkan file arsip terpisah, cukup periksa per commit
Masalahnya memang jika repositori dipindahkan maka import path ikut berubah, tetapi itu juga bisa dianggap sebagai semacam keuntungan
Selain itu saya tidak terlalu paham apa manfaat nyata dari adanya tahap publish terpisah
Rasanya seperti peninggalan zaman lama saat orang mengunggah arsip tar lewat FTP
Dulu saya pernah mengerjakan repositori bersama bernama angulartics2
Di sana masih ada GitHub Actions secret berisi token npm dengan hak publish yang sangat luas
Salah satu kolaborator juga ternyata punya hak atas beberapa proyek, dan kemungkinan itulah sebabnya beberapa paket terdampak sekaligus
Branch baru bernama Shai-Hulud di-force-push bersama workflow GitHub Action berbahaya
Karena kolaborator itu punya hak admin, workflow langsung berjalan tanpa perlu review dan token npm pun bocor
Dengan token yang bocor itu, versi berbahaya dipublikasikan ke 20 paket
Sebagian besar bukan paket yang banyak dipakai, tetapi @ctrl/tinycolor adalah paket populer dengan sekitar 2 juta unduhan per minggu
Yang masih belum saya pahami adalah bagaimana token npm dari repositori angulartics2 bisa juga dipakai untuk mempublikasikan tinycolor
Saya juga punya hak admin di repositori npm milik orang lain, dan sebagian besar rilis terbaru memang hampir selalu saya yang lakukan
Setelah jadi admin, saya malah jadi ingin memperbaiki berbagai masalah lama yang selama ini dibiarkan, jadi commit atas nama saya juga makin banyak
Saya sebenarnya sudah hampir memutuskan untuk mempublikasikan paket lewat GitHub Action, tetapi saya selalu khawatir kalau saat deploy manual dengan 2FA saya malah tanpa sengaja merilis sesuatu yang bukan dari master
Karena masalah seperti ini saya terus menunda membahasnya dengan admin lain, dan melihat kejadian sekarang, rasanya justru bagus saya sempat menunda
Saya tidak tahu jawaban yang benar, tetapi menyerahkan kredensial ke pihak ketiga jelas tidak terasa sebagai solusi yang baik
Maaf kalau penjelasan saya sebelumnya kurang jelas
Token ini punya hak publikasi global ke seluruh paket npm saya
Selama 10 tahun terakhir saya terus mendukung rilis manual
Saya selalu mendapat banyak tentangan, tetapi belakangan ini gagasan itu tampaknya tidak lagi terdengar aneh
Saya tahu CI/CD terdengar keren, tetapi melihat kasus ini dan insiden CF baru-baru ini, semakin banyak bukti bahwa otomatisasi justru bisa membuat masalah serius lebih mudah terjadi
Dulu saat bekerja di BigBank, setiap deployment produksi harus melibatkan setidaknya lima orang yang siaga bersama dan melewati banyak prosedur, tetapi setidaknya kami benar-benar tahu apa yang sedang kami deploy
Bukan karena GitHub Actions atau skrip rilis otomatis itu buruk, tetapi saya merasa cara lama seperti membangun secara manual, menandatangani, mengunggah tarball, lalu memverifikasinya jauh lebih aman
Sistem distribusi paket, seperti sistem packaging distro misalnya Debian, juga punya tahap verifikasi terpisah, dan itulah salah satu alasan mengapa saat insiden xz internet tidak langsung diretas total
Setidaknya harus ada tahap wajib di mana manusia benar-benar menandatangani binary sebelum rilis dipublikasikan
Tentu ada masalah bahwa penyerang bisa menambahkan dirinya sebagai maintainer utama dan menandatangani dengan kuncinya sendiri, jadi agar lebih aman tetap perlu ada pengelolaan kunci tepercaya seperti pada sistem packaging distro
Kalau threat model saya didasarkan pada gagasan bahwa "kalau satu akun GitHub atau satu API key bocor, seluruh pengguna langsung terkompromi", maka saya benar-benar perlu bertanya apakah model itu masuk akal
Memakai 2FA untuk publikasi memang bagus, tetapi akan jauh lebih aman jika beberapa penulis harus sama-sama menyetujui dengan tanda tangan kriptografis
Jangan sampai serangan berhasil hanya karena satu orang saja yang ditembus
Banyak paket memang hanya punya satu penulis
Mewajibkan tanda tangan dari beberapa penulis memang bagus, tetapi kalau commit, tag, dan artefak semuanya diverifikasi tanda tangannya dalam bentuk apa pun, sebagian besar serangan bisa dicegah
Packaging distro mendukung verifikasi tanda tangan dengan sangat baik, tetapi package manager bahasa pemrograman masih lemah di sisi itu
Sebagai contoh, proses rilis resmi runc semuanya ditandatangani dengan kunci maintainer, dan kuncinya disimpan di Yubikey atau perangkat serupa
Sistem distro juga mengelola keyring terpisah untuk memverifikasi sumber resmi dan binary
Kalau proses seperti ini ada, saya rasa serangan kali ini bisa dihentikan di beberapa tahap
Build boleh saja dilakukan langsung di CI, tetapi pada tahap akhir tetap harus ada tanda tangan langsung dari maintainer
Kalau workflow seperti ini belum ada di package manager bahasa, maka Trusted Publishing adalah alternatif yang setidaknya tidak terlalu buruk
Tetapi kalau akun GitHub disusupi, misalnya lewat pencurian cookie, publikasi tetap bisa langsung dilakukan
GitHub memang mendukung pengaturan keamanan seperti timeout untuk Trusted Publishing, tetapi penyerang juga bisa mematikannya
Kalau akun saya dibobol, sistem distro tetap tidak akan menerima perubahan yang ditandatangani dengan kunci selain milik saya, jadi relatif lebih aman
Catatan: saya bekerja di SUSE, tetapi saya berharap dukungan verifikasi artefak semakin luas di openSUSE, Arch, Gentoo, dan lainnya
Tautan terkait:
runc.keyring
keyring_validate.sh
release_sign.sh
runc.keyring milik openSUSE
Saya sangat membenci token
Token pada dasarnya hanyalah kata sandi statis
Menurut saya kita butuh bentuk autentikasi yang lebih layak
Sebagai contoh, menggunakan GitHub sebagai penyedia token untuk AWS menurut saya termasuk pendekatan yang lebih masuk akal
Integrasi GitHub-AWS dengan OIDC
Namun ini lebih merupakan kasus pengecualian
Alur OIDC antar-mesin sebenarnya bisa aman jika diimplementasikan dengan baik, tetapi konfigurasinya terlalu rumit
Dan pada akhirnya OIDC juga terasa seperti "token yang lebih rumit"
Kalau lingkungannya otomatis dan tidak ada verifikasi manusia langsung, akan selalu ada sesuatu yang bisa bocor di suatu tempat, entah itu token atau pembuat tokennya
Bahkan pada kasus worm kali ini, OIDC bukan solusi mendasar
Kalau workflow GitHub sudah ditembus, dengan atau tanpa OIDC lingkungan itu tetap hanya akan disuntikkan identitas sementara
Pada akhirnya yang penting adalah memastikan workflow yang memegang secret tidak bisa dijalankan oleh pengguna yang tidak berwenang
Kalau ingin pembagian hak akses yang lebih rinci, membatasi scope token mungkin justru lebih efektif daripada OIDC
Tujuan asli token adalah agar masa berlakunya dan cakupan izinnya (authZ) terbatas
Tetapi dalam kebanyakan kasus praktiknya tidak begitu, dan token hanya dipakai secara statis seperti kata sandi
Ada alternatif seperti oauth atau biscuits yang memungkinkan pembatasan izin lebih rinci, tetapi jarang dipakai di dunia nyata
Trusted Publishing sekarang didukung oleh beberapa package registry termasuk npm
Kabar terkait
Seperti yang juga disebut orang lain, token seharusnya hanya diterbitkan dengan masa hidup pendek atau setelah autentikasi manual seperti MFA, passphrase, dan sebagainya
Menggunakan mTLS (sertifikat klien TLS) tampaknya lebih mendekati arah jawaban yang benar
Apakah ada yang tahu tool/skrip publik untuk memeriksa paket npm yang rentan?
Sepertinya halaman stepsecurity tidak menyediakan alat seperti itu
Tidak bisa mencegah semuanya, tetapi mengadopsi provenance-action juga ide yang bagus
provenance-action
Untuk isu yang sudah dikenal,
npm auditadalah pilihan dasarnyaMaksud saya hanya bahwa pada publikasi lokal saya agak khawatir pada kesalahan seperti salah branch atau build yang terlewat
Saya jadi bertanya-tanya bagaimana kalau sebuah job CI melakukan force-push perubahan jauh ke dalam riwayat git
Status quo saat ini jelas sudah tidak lagi berfungsi dengan baik
Tentu kita bisa memuji kelebihan teknis seperti token OIDC atau solusi zero-trust
Tetapi kenyataannya, banyak maintainer library npm dengan jutaan unduhan baru akan peduli keamanan setelah mereka diretas atau setelah npm langsung memblokir distribusinya
Lalu akan muncul juga usulan yang tidak realistis seperti "hapus semua dependensi dan pakai standard library saja"
Mengurangi dependensi memang bagus, tetapi itu sama sekali bukan solusi untuk masalah yang sudah ada sekarang
Secara realistis pilihannya tinggal dua: entah puluhan ribu atau ratusan ribu orang meninggalkan npm dan menulis ulang semuanya, atau npm yang memaksa aturan seperti 2FA dan OIDC terutama pada paket dengan unduhan tinggi, dan memblokir publikasi jika aturannya tidak dipatuhi
Mana yang lebih realistis untuk dijalankan rasanya sudah jelas
Kalau tidak, reputasi npm akan jatuh total dan kita hanya akan mendapat situasi seperti XKCD 927