Salah satu library matematika di npm ternyata menyimpan remote access implant yang dienkripsi dan didesain tidak aktif sampai korbannya menjalankan satu persamaan tertentu. Kasus ini dibedah publik oleh tim SafeDep lewat postingan 18 September 2026, dan polanya jauh lebih licik daripada malware npm pada umumnya. Tidak ada install hook, tidak ada kode mencurigakan yang langsung jalan, dan source code di GitHub-nya bersih. Kodenya baru "bangun" ketika fungsi solver dipakai menghitung matriks dengan nilai yang sangat spesifik.
TL;DR
- Paket npm bernama mathmain, kembaran mathjs, menyimpan remote access implant terenkripsi yang baru aktif saat fungsi solver dijalankan dengan input tertentu.
- Password dekripsinya adalah hasil JSON.stringify dari matriks Pascal 3x3, yaitu [[1,1,1],[1,2,3],[1,3,6]], sehingga kodenya tampak iner untuk hampir semua penggunaan.
- Loader tidak ada di repository GitHub, melainkan disisipkan saat build dipublikasikan ke registry, ditemukan identik di lima versi lintas tiga paket: mathmain, mathsbase, dan math-universe.
- Angka unduhan paket tersebut sangat tinggi, mathmain 605.157, mathsbase 1.923.059, dan math-universe 569.730 untuk rentang 12 sampai 18 September 2026, tetapi dicurigai sebagai metrik manipulasi.
- SafeDep menerbitkan laporan lengkapnya pada 18 September 2026 dengan indikator compromise dan hash file yang bisa dipakai untuk memeriksa sistem.
Artikel ini mengurai cara kerja loader tersebut, kenapa mekanisme enkripsinya bikin deteksi biasa jadi tidak berguna, dan langkah konkret yang bisa diambil developer Indonesia yang dependensi npm-nya mungkin ikut kepasang.
mathmain: Kembaran mathjs yang Menyimpan Sesuatu
Paket bermasalahnya bernama mathmain. Secara tampilan, ini praktis kembaran mathjs, library matematika JavaScript yang sangat populer, dengan nama berbeda dan kode yang diobfuscasi. Analisis SafeDep dimulai pada 17 September 2026, dan yang membuat mereka curiga bukan manifest-nya, bukan juga install script, melainkan satu extra call yang nyelip di dalam fungsi lusolve(), solver untuk sistem persamaan linear.
Di build CommonJS-nya, setelah hasil kalkulasi selesai, ada pemanggilan tambahan ke removeSolveValidation() yang mengirim data matriks segitiga bawah. Hasil pemanggilannya disimpan ke variabel yang tidak pernah dipakai lagi. Sepintas terlihat seperti kode validasi sisa build. Ternyata fungsi itu adalah pintu masuk ke rantai dekripsi.
Dari situ alurnya bergerak ke fungsi isGraph() di file lib/cjs/utils/is.js. Fungsi ini mengkonversi inputnya menjadi string JSON, lalu memakai string itu sebagai password untuk membongkar sebuah blob base64 yang tertanam di file yang sama. Blob itu pertama-tama didekripsi menjadi nama file, lalu file hasil dekripsi ditulis ke disk dan dimuat dengan require(). Kode yang lolos dari proses itu berjalan dengan izin penuh setara proses Node.js.
Enkripsi yang Kuncinya adalah Data Matematika
Bagian paling aneh dari kasus ini: password-nya bukan string statis yang bisa dicari dengan grep. Loader ini memakai skema yang cukup serius: turunan key dengan scrypt sepanjang 256 bit, lalu dekripsi AES-256-GCM. Layout blob-nya tetap, 16 byte salt, 12 byte initialization vector, 16 byte authentication tag, sisanya ciphertext, semuanya dibungkus base64.
Password yang dipakai adalah hasil JSON.stringify() dari matriks L (faktor segitiga bawah dari dekomposisi LU). Artinya, kodenya hanya terbuka kalau ada program yang memanggil solver dengan matriks yang menghasilkan string persis sama. Salah satu angka saja, cek autentikasi AES-GCM gagal, tidak ada file yang ditulis, dan tidak ada perilaku mencurigakan yang muncul.
Pemicunya akhirnya teridentifikasi: inputnya adalah matriks Pascal 3x3, yaitu [[1,1,1],[1,2,3],[1,3,6]]. Ketika matriks itu didekomposisi secara LU, faktor L-nya menjadi [[1,0,0],[1,1,0],[1,0.5,1]], dan bentuk JSON dari matriks itulah password-nya. SafeDep menyebut JFrog lebih dulu melaporkan input pemicu ini, lalu mereka mereproduksinya terhadap file mathmain. Hasilnya konsisten: password yang sama membuka seluruh keluarga paket ini.
Tiga File Besar Berisi Ciphertext, Bukan JavaScript
Di direktori utils paket tersebut, tim SafeDep menemukan tiga file yang isinya bukan kode JavaScript normal, melainkan data base64 berukuran besar:
graph.jssekitar 20.918 byte ciphertextfraction.jssekitar 9.084 bytebignumber/type.jssekitar 1.179.416 byte
Dua file terakhir tidak dirujuk oleh loader yang terlihat. Keduanya baru dipanggil setelah stage pertama, graph.js, berhasil didekripsi dan dieksekusi. Dari hasil analisis statik terhadap kode yang sudah terbuka, file-file itu membentuk implant akses jarak jauh: stage pertama mengumpulkan data host, membuat pasangan kunci X25519 lewat modul crypto Node, dan punya jalur eksekusi perintah shell lewat child_process. Kanal perintahnya tidak memakai server C2 konvensional, tapi menumpang pada layanan chat publik dan jaringan blockchain, kombinasi yang makin sering dipakai malware modern supaya traffic-nya sulit diblokir.
Sumbernya Bukan di GitHub, Melainkan di Proses Publish
Detail yang bikin kasus ini penting untuk dipahami: dua paket saudaranya, mathsbase dan math-universe, menautkan repository GitHub publik. Keduanya dibaca tim SafeDep, dan di commit yang dituju, kode loader itu tidak ada. Solver di sumber GitHub mengakhiri fungsinya dengan rapi tanpa extra call. Loader itu baru ditambahkan pada saat build dipublikasikan ke registry.
Ini menegaskan satu kelas risiko yang sering terlewat: audit terhadap repository saja tidak cukup, karena artefak npm yang terpasang di mesin developer tidak wajib identik dengan sumbernya. Loader yang sama ditemukan di lima versi lintas tiga paket itu. Untuk mathmain sendiri, versi default yang diserve registry pada 17 September (1.5.3) justru bersih, sementara versi 1.0.1 yang membawa implant. Jadi cek satu baris ke versi terbaru saja, malware-nya lolos.
Angka Download yang Tidak Bisa Dipercaya
SafeDep memeriksa statistik unduhan registry pada 19 September untuk tiga paket tersebut, mencakup rentang 12 sampai 18 September 2026 di semua versi. Angkanya fantastis: mathmain 605.157 unduhan, mathsbase 1.923.059, dan math-universe 569.730.
Tapi tim itu sendiri langsung memberi peringatan: angka-jangan dibaca sebagai jumlah instalasi nyata. npm pada periode yang sama melaporkan nol unduhan untuk seluruh registry pada 17 September, yang membuat hitungan sebelumnya tidak bisa dijadikan acuan. Paket-paket ini juga tidak punya dependents publik, dan traffic di jaringan konten jsDelivr nyaris nol. Sampai postingan diterbitkan, tidak bisa ditentukan apa yang menghasilkan volume sebesar itu, dan berapa banyak (kalau ada) sistem yang benar-benar menjalankan kode terenkripsinya.
Terus, kenapa angka download tidak jujur? Untuk paket yang belum diadopsi siapa pun, lonjakan tidak wajar adalah sinyal itu sendiri: manipulasi metrik adalah cara klasik menaikkan skor popularitas palsu supaya paket terlihat sah oleh manusia maupun oleh mesin rekomendasi otomatis.
💬 Komentar (0)
Belum ada komentar. Jadilah yang pertama! 💬