Kembali ke Blog

Checklist Saya Tiap Kali Ada Serangan Supply-Chain npm Baru

#security#npm#supply-chain
Checklist Saya Tiap Kali Ada Serangan Supply-Chain npm Baru

Kayaknya tiap beberapa bulan sekali pasti ada headline baru: package populer di npm kecompromise, maintainer kena phishing, atau ada worm yang nyebar lewat postinstall script terus diam-diam nyolong token dari CI orang. Dulu saya cuma baca judulnya, mikir “untung bukan dependency saya,” terus lanjut kerja kayak biasa. Sekarang, dengan beberapa project client jalan bareng-bareng plus situs ini sendiri, sikap cuek kayak gitu udah nggak masuk akal. Jadi ada rutinitas yang beneran saya jalanin tiap kali insiden baru muncul di linimasa — bukan cuma dibaca terus lupa lagi tiga hari kemudian.

Cek dulu package mana yang beneran kena

Judul berita selalu bikin serem — “serangan supply-chain npm terbesar sepanjang sejarah” atau semacamnya — padahal begitu dibuka, detailnya biasanya spesifik banget. Satu package, satu range versi, kadang cuma satu maintainer yang akunnya kebobol lewat phishing. Saya nggak pernah percaya newsletter atau thread X buat ini. Langsung ke GitHub Security Advisory atau halaman audit resminya, catat nama package sama range versi yang kena, baru mikir apa itu related ke stack saya sama sekali.

Kalau ternyata nggak related — ya udah, lanjut kerja. Separuh dari “insiden” yang bikin heboh linimasa itu nggak nyentuh saya sama sekali.

Diff lockfile, jangan cuma install ulang

Kalau ada yang match, saya nggak langsung percaya npm audit doang. Saya jalanin npm ls <nama-package> di tiap repo buat liat itu dependency langsung atau numpang lewat sesuatu yang lain, terus beneran buka package-lock.json buat cek versi exact yang ke-lock. Kalau ternyata versi yang ke-lock ada di luar range yang kena, saya catet aja buat upgrade nanti — nggak saya treat sebagai darurat.

Token dan credential CI, saya revoke duluan

Ini bagian yang paling gampang di-skip pas lagi buru-buru, padahal paling penting. Kalau ada kemungkinan realistis satu dependency saya kena compromise, semua secret yang kepake di CI/CD-nya — npm publish token, GitHub Actions secret, deploy key ke VPS — saya anggap berpotensi bocor, dan saya rotate itu duluan sebelum ngurusin hal lain. Nggak mahal kok, cuma butuh beberapa menit generate ulang. Nunggu sampai “yakin dulu beneran kena” itu logika kebalik. Rotate duluan, investigasi belakangan.

npm audit saya tetep jalanin, tapi nggak saya percaya penuh. Tool itu bagus buat vulnerability yang udah ke-disclose resmi, tapi kebanyakan insiden supply-chain belakangan ini bentuknya social engineering ke maintainer atau token yang kecuri — bukan vulnerability code yang bisa ke-scan otomatis. Artinya audit bisa hijau bersih padahal ada masalah aktif yang belum sempet ke-flag. Makanya saya masih langganan beberapa advisory feed manual juga.

Postinstall script yang saya curigain, bukan dependency-nya

Pola serangan yang paling sering saya baca belakangan lewat script yang otomatis jalan pas npm install, bukan lewat kode yang beneran ke-import. Buat project baru atau dependency yang jarang saya pakai, saya suka intip dulu package.json-nya — ada postinstall atau preinstall script nggak, sebelum instal beneran. Kalau ada dan saya nggak yakin kenapa itu perlu, saya install pakai --ignore-scripts dulu, cek manual scriptnya, baru enable kalau emang legit.

Kerja di project client bikin ini lebih ribet, bukan lebih gampang. Repo sendiri gampang dikontrol disiplinnya. Tapi codebase client sering punya lockfile yang jarang di-refresh, dependency yang udah lama nggak diaudit, kebijakan yang beda-beda soal siapa boleh nambah package. Saya nggak bisa maksain standar sendiri ke semua project, tapi minimal saya jalanin audit check ini secepatnya begitu ada insiden besar, dan saya kasih tau client kalau ternyata ada exposure beneran. Diemin karena nggak enak nanya-nanya soal repo yang bukan punya saya — itu bukan opsi.

Saya juga jadi lebih pelit nambah dependency baru dibanding dulu. Bukan karena paranoid sama open-source, tapi karena tiap dependency baru nambah attack surface yang saya nggak kontrol langsung. Sebelum nambah package buat hal kecil yang sebenernya bisa saya tulis sendiri dalam 20 baris, sekarang saya mikir dua kali dulu.

Nyatet tiap insiden, biar nggak ngulang belajar hal yang sama

Awalnya saya nggak punya sistem sama sekali — tiap insiden direspon dari nol, coba inget-inget lagi langkah kemarin. Sekarang ada satu file markdown sederhana per client (atau satu buat semua project pribadi) isinya tanggal insiden, package yang kena, langkah yang saya jalanin, berapa lama makan waktu. Nggak fancy. Tapi pas insiden baru muncul, saya bisa cek pola dari yang sebelumnya — dan dari situ saya baru sadar tiga dari lima insiden terakhir lewat dependency transitif yang sama. Berarti ada satu titik lemah yang emang pantas dapet perhatian ekstra.

Saya juga sempet kebablasan ke arah sebaliknya — beberapa bulan pertama serius soal ini, tiap notifikasi security advisory dari GitHub langsung bikin saya stop kerjaan buat investigasi, padahal kadang itu cuma dev dependency yang nggak pernah masuk production bundle. Butuh beberapa bulan buat kalibrasi ulang: sekarang saya bedain dulu production apa dev-only, direct apa transitive yang dalem, baru mutusin urgent apa nggak.

Checklist ini nggak makan waktu lama — paling 20-30 menit per insiden buat semua project saya. Tapi 20-30 menit itu jauh lebih murah dibanding beresin akibat token bocor atau deploy yang kecompromise diam-diam tanpa ketauan berminggu-minggu.

Bukan berarti saya jadi kebal. Risiko di ekosistem sebesar npm itu nggak bisa dihilangin total, cuma bisa dikelola. Tapi setelah beberapa kejadian besar tahun ini, saya lebih percaya rutinitas boring yang konsisten ini dibanding cuma berharap dependency saya nggak pernah kena giliran.