Antwa CodeAntwaCode Blog

Catatan11 menit baca

Node.js Rilis Keamanan Oktober 2026: 10 CVE, Brotli RCE, dan Kompromi eMudhra CA

Node.js 22.23.4, 24.22.1, dan 26.12.1 menambal 10 vulnerability runtime — termasuk Brotli RCE, trio bypass verifikasi TLS, dan insiden kompromi eMudhra CA. Ringkasan lengkap, profil risiko, dan cara update-nya.

Baca dalam English →

nodejs/node repository Gambar: GitHub — repositori nodejs/node

Baru sehari setelah dunia PHP digemparkan PHP2Shell, giliran ekosistem Node.js yang mendapat rilis keamanan besar. Tepat pada 21 Oktober 2026, tim Node.js merilis versi baru untuk tiga release line yang didukung — v22.23.4 (LTS "Jod"), v24.22.1 (LTS "Krypton"), dan v26.12.1 (Current) — yang menambal 10 vulnerability di runtime sekaligus menangani insiden kompromi certificate authority.

Empat dari sepuluh bug berstatus High, termasuk satu yang secara eksplisit dinyatakan memungkinkan remote code execution: bug out-of-bounds write di decoder Brotli. Sisanya mencakup tiga bypass verifikasi hostname TLS, bug DNS, masalah unik di crypto.randomUUID(), dan beberapa lubang kecil di Permission Model.

Di artikel ini kita bedah satu per satu: apa yang rusak, kenapa itu penting, dan apa yang harus kamu lakukan hari ini juga.

Sekilas: Sepuluh Lubang Sekaligus

Sebelum masuk ke detail, ini peta cepatnya. Node.js tidak menerbitkan skor CVSS resmi untuk issue-issue ini; severity di bawah adalah rating dari proyek Node.js sendiri:

CVESeverityMasalahTerdampak
CVE-2026-111497HighBrotli decoder OOB write → RCE22.x, 24.x, 26.x
CVE-2026-105482Highdns.resolve memotong nama yang mengandung karakter NUL22.x, 24.x, 26.x
CVE-2026-105483HighBypass hostname TLS saat IP ditulis dengan digit fullwidth24.x, 26.x
CVE-2026-106069HighBypass hostname TLS saat host "longgar" resolve ke IP22.x, 24.x, 26.x
CVE-2026-105481MediumKeep-alive socket memproses response yang ditulis sebelum request terkirim22.x, 24.x, 26.x
CVE-2026-106072MediumValidasi sertifikat buruk untuk hostname IPv4 non-kanonik22.x, 24.x, 26.x
CVE-2026-106074MediumrandomUUID()/randomInt() mengulang nilai di snapshot/SEA22.x, 24.x, 26.x
CVE-2026-106070LowZipFile mengembalikan byte prefix yang dikontrol attacker26.x
CVE-2026-106071LowPermission Model over-grant via wildcard radix lookup26.x
CVE-2026-106073LowBypass Permission Model lewat fs.realpathSync22.x, 24.x, 26.x

Catatan penting dari advisory: versi end-of-life selalu terdampak setiap kali security release keluar, dan mereka tidak akan menerima perbaikan ini. Kalau masih pakai Node.js 20.x atau lebih tua, tidak ada patch yang menunggu kamu — satu-satunya jalan adalah pindah ke release line yang didukung.

Highlight: Brotli RCE (CVE-2026-111497)

Ini dia yang paling bikin deg-degan. Decoder Brotli di Node.js punya out-of-bounds write yang bisa dimanfaatkan untuk remote code execution. Brotli adalah format kompresi yang dipakai luas — dari Content-Encoding: br di HTTP, zlib.createBrotliDecompress(), sampai aset statis yang dikompres. Artinya, data terkompresi yang datang dari pihak luar bisa berakhir di decoder yang rusak ini.

Detail teknisnya sengaja dibuat tipis oleh Node.js (seperti biasa untuk advisory yang belum semua orang sempat patch): advisory tidak menyebut input persis apa yang memicu bug-nya, dan tidak mengonfirmasi apakah jalurnya langsung bisa dicapai di setup default. Yang jelas:

  • Bug-nya ada di decoder Brotli bawaan Node.js (bundled dependency).
  • Ditemukan oleh Matteo Collina (mcollina) dan diperbaiki oleh Antoine du Hamel (aduh95) dengan cherry-pick commit upstream dari Evgenii Kliuchnikov di repositori Brotli.
  • Terdampak di ketiga release line: 22.x, 24.x, dan 26.x.

Karena ini OOB write, dampaknya bukan cuma crash — OOB write adalah kelas bug yang secara klasik mengarah ke kontrol eksekusi. Perlakukan ini sebagai yang paling urgent dari kesepuluhnya, terutama kalau aplikasi kamu memproses arsip, aset, atau request dengan Content-Encoding: br dari user atau upstream yang tidak dipercaya.

Siapa yang Paling Berisiko?

Sebenarnya semua yang menjalankan Node.js 22.x/24.x/26.x sebaiknya update — tapi kalau mau memprioritaskan, ini profil risikonya dari yang paling urgent:

🔴 Prioritas tinggi: yang memproses data terkompresi dari pihak luar Proxy, API gateway, CDN origin, layanan yang menerima Content-Encoding: br, aplikasi yang mengekstrak arsip ZIP, atau image/asset pipeline — semua menyentuh langsung Brotli decoder (CVE-2026-111497) dan ZIP parser (CVE-2026-106070). Kalau data yang masuk datang dari user atau upstream yang tidak sepenuhnya kamu percaya, ini jalur langsung ke OOB write.

🔴 Prioritas tinggi: yang melakukan koneksi TLS ke endpoint IP Microservice yang saling memanggil lewat IP langsung, koneksi ke database berbasis IP, webhook, atau agent yang memverifikasi sertifikat lawan bicara — persis di sinilah trio bypass TLS hostname bermain. Sertifikat untuk domain attacker bisa "mewakili" endpoint IP yang kamu tuju.

🟡 Prioritas sedang: yang mengandalkan validasi nama host Aplikasi dengan proteksi SSRF, allowlist domain, atau keputusan keamanan berbasis hostname perlu memperhatikan CVE-2026-105482 (pemotongan NUL) dan memaudit alur validasinya.

🟡 Prioritas sedang: yang mendistribusikan SEA atau startup snapshot CLI tool yang dikompilasi jadi executable tunggal, installer desktop, atau aplikasi apa pun yang dibangun dengan V8 snapshots — bug randomUUID() (CVE-2026-106074) membuat setiap salinan executable menghasilkan "angka acak" yang sama. Kalau produk kamu diedarkan ke banyak user dalam bentuk ini, pertimbangkan ini insiden keamanan, bukan sekadar bug.

🟢 Prioritas rendah tapi tetap update: yang memakai Permission Model Fitur --permission masih tergolong muda, dan dua bug Low ini cukup untuk menjebol isolasinya. Kalau kamu memakainya sebagai lapisan keamanan nyata (bukan sekadar eksperimen), update wajib.

Dan satu profil yang sering terlupa: aplikasi yang dibungkus Electron atau framework desktop. Electron membawa runtime Node.js sendiri yang tidak selalu sinkron dengan update sistem. Cek versi runtime di dalamnya, bukan cuma node -v di terminal.

Tiga Bypass Verifikasi Hostname TLS — Satu Pola, Tiga Jalan

Yang menarik dari rilis ini adalah tiga CVE terpisah yang berbagi pola serangan yang sama: sebuah alamat ditulis dalam bentuk yang tidak biasa, Node.js tidak mengenalinya sebagai alamat IP, lalu pemeriksaan sertifikat "jatuh" ke nama DNS — sehingga sertifikat yang diterbitkan untuk sebuah domain bisa menjamin koneksi ke endpoint IP. Intinya: attacker yang punya sertifikat valid untuk domainnya sendiri bisa meyakinkan klien bahwa koneksi ke IP target itu sah.

CVE-2026-105483 — IP dengan Digit Fullwidth (High, 24.x & 26.x)

Saat alamat IP ditulis memakai digit fullwidth (varian Unicode dari angka, misalnya 127.0.0.1), validasi hostname sertifikat TLS bisa dilewati. Node.js tidak mengenali bentuk ini sebagai IP, jadi verifikasi jatuh ke DNS SANs. Ditemukan oleh hasanfleyah, diperbaiki oleh James Snell (jasnell) dengan memperbaiki regresi normalisasi IP.

CVE-2026-106069 — Host yang "Longgar" Resolve ke IP (High, 22.x, 24.x, 26.x)

Bypass kedua terjadi saat sebuah host resolve ke alamat IP dengan cara yang longgar. Mekanismenya sama: alamat tidak dikenali sebagai IP, pemeriksaan jatuh ke DNS names, dan sertifikat domain bisa mewakili endpoint IP. Ditemukan oleh anagnorisis2peripeteia, diperbaiki oleh Matteo Collina.

CVE-2026-106072 — IPv4 Non-Kanonik & DNS SANs (Medium, 22.x, 24.x, 26.x)

Kasus ketiga: hostname IPv4 dalam bentuk non-kanonik (misalnya 2130706433 atau 0x7f.1 — ya, yang lama-lama bikin pusing kalau pernah main-main dengan IP aneh) membuat validasi sertifikat tidak proper, sehingga DNS SANs diizinkan mengautentikasi endpoint IP. Ditemukan oleh br41ny, diperbaiki oleh Matteo Collina.

Perbaikannya

Semua jalur ini ditutup dengan pendekatan yang sama: TLS sekarang menolak alamat IP non-kanonik dan memperbaiki regresi normalisasi IP. Kalau aplikasi kamu melakukan koneksi TLS ke endpoint berbasis IP — internal service, database, webhook, koneksi antar-microservice — pastikan runtime-nya sudah di-update, karena persis di situlah kelas bypass ini berbahaya.

Cerita Tambahan: Kompromi eMudhra CA

Rilis ini juga memuat langkah darurat yang bukan bug Node.js sama sekali, tapi sama pentingnya: penanganan kompromi certificate authority eMudhra.

Kronologinya (dikutip dari laporan Mozilla):

  • Sabtu, 17 Oktober 2026 — Mozilla menerima laporan bahwa private key untuk 8 sertifikat intermediate eMudhra telah dikompromikan.
  • eMudhra menyatakan intermediate yang terdampak berasal dari key generation ceremony April 2025, dan investigasi masih berlangsung.
  • Dampaknya: attacker yang memegang key tersebut bisa menerbitkan sertifikat HTTPS palsu untuk situs mana pun yang tidak mereka miliki.

Respons Node.js (dan Mozilla):

  • Semua rilis keamanan ini sekarang menolak TLS chain yang mengandung public key yang diblokir.
  • Root certificates bawaan di-update ke NSS 3.131.1 — rilis trust store Mozilla yang mencabut root yang menandatangani intermediate yang terdampak.

Pelajarannya: keamanan TLS bukan cuma soal bug di kode verifikasi kita. Chain kepercayaan di atasnya — root CA, intermediate CA — bisa runtuh kapan saja, dan runtime harus cukup cepat mencabut kepercayaannya. Inilah kenapa update rutin itu penting bahkan kalau kode kamu sendiri tidak berubah.

dns.resolve dan Karakter NUL (CVE-2026-105482)

Bug High lainnya: dns.resolve memotong (truncate) nama yang mengandung karakter NUL (\0). Masalah klasik C-string yang menyusup ke dunia JavaScript. Dampaknya bisa bermacam-macam tergantung aplikasi: nama host yang seharusnya ditolak jadi "dipendekkan" menjadi nama lain yang valid — potensi logika keamanan yang salah, misalnya allowlist safe.example.com\0.evil.com yang dipotong jadi safe.example.com.

Node.js kini memvalidasi semua input resolve terhadap null bytes sebelum diproses. Ditemukan oleh hasanfleyah, diperbaiki oleh James Snell.

Kalau aplikasi kamu memvalidasi nama host untuk keputusan keamanan (SSRF protection, allowlist, CORS), ini saatnya audit: jangan pernah mengandalkan normalisasi nama host yang dilakukan setelah validasi.

Bug Unik: randomUUID()/randomInt() Mengulang Diri di Snapshot (CVE-2026-106074)

Ini mungkin bug paling "unik" di rilis ini. Aplikasi Node.js yang dibuat memakai user-land startup snapshots atau Single Executable Applications (SEA) bisa menghasilkan nilai acak yang sama di setiap proses.

Ceritanya begini: crypto.randomUUID() dan crypto.randomInt() menyimpan entropy cache untuk performa. Nah, cache ini ikut "tersimpan" ke dalam snapshot saat build. Setiap proses yang dijalankan dari snapshot tersebut memulai hidupnya dengan cache yang sama — sehingga nilai "acak" yang dikeluarkan berulang persis di setiap proses.

Bayangkan dampaknya:

  • Token reset password yang dibuat saat startup selalu sama.
  • ID sesi atau API key yang digenerate dengan randomUUID() bisa diprediksi attacker yang menjalankan build yang sama.
  • Nilai acak untuk kriptografi yang ternyata tidak acak — mimpi terburuk developer keamanan.

Perbaikannya (oleh Filip Skokan / panva, atas laporan gesposito): cache entropy kini dihapus (reset) antar-snapshot. Tapi perbaikan runtime saja belum cukup buat kamu — snapshot/SEA yang sudah kamu build dengan runtime lama masih membawa cache yang rusak dan wajib di-build ulang dengan Node.js versi baru. Ini poin operasional yang gampang terlewat!

Sisanya: HTTP Keep-alive, ZIP, dan Permission Model

CVE-2026-105481 — Keep-alive Socket (Medium, semua line)

Socket keep-alive bisa memproses response yang ditulis sebelum request-nya terkirim. Dalam skenario connection reuse yang rusak, data bisa tertukar antar-request — klasik masalah "response mix-up" yang berbahaya di proxy atau koneksi persistent. Ditemukan hasanfleyah, diperbaiki James Snell dengan memastikan agent data guard bekerja tanpa I/O.

CVE-2026-106070 — ZIP Prefix Bytes (Low, 26.x)

ZipFile bisa mengembalikan byte prefix yang dikontrol attacker setelah validasi header ZIP gagal. Alih-alih gagal bersih, parser meninggalkan sisa data attacker di output. Ditemukan startimeash, diperbaiki Matteo Collina dengan menghindari caching ZIP local header yang tidak valid.

CVE-2026-106071 & CVE-2026-106073 — Permission Model (Low)

Dua lubang di Permission Model Node.js (fitur --permission):

  • CVE-2026-106071 (26.x): filesystem over-grant lewat wildcard radix lookup — izin bisa terbuka lebih luas dari yang diminta. Ditemukan malikhamzaiqbal, diperbaiki James Snell.
  • CVE-2026-106073 (semua line): bypass Permission Model lewat fs.realpathSync. Ditemukan 0xoroot, diperbaiki RafaelGSS.

Meski "Low", kalau kamu mengandalkan Permission Model sebagai lapisan isolasi keamanan (misalnya membatasi akses filesystem aplikasi pihak ketiga), dua bug ini cukup untuk menjebol batasannya. Update wajib.

Update Dependensi yang Ikut Terbawa

Rilis keamanan ini juga memperbarui dependensi bawaan yang punya vuln publiknya sendiri:

  • OpenSSL 3.5.9 (24.x, 22.x) — perbaikan keamanan di library TLS/crypto.
  • c-ares 1.34.9 (semua line) — library resolver DNS async.
  • SQLite 3.53.4 (22.x) — database embedded bawaan.
  • Undici (semua line — 6.29.1 untuk 22.x, 7.30.1 untuk 24.x) — HTTP client bawaan Node.js.
  • Root certificates NSS 3.131.1 (semua line) — termasuk pencabutan trust eMudhra.
  • Timezone data 2026e (22.x) dan backport V8.
  • Ada juga hardening konversi dan formatting X.509 dari Filip Skokan.

Kalau kamu pikir "Node.js cuma runtime, dependensinya aman karena teruji" — ingat bahwa OpenSSL, c-ares, dan Undici masing-masing punya riwayat CVE-nya sendiri. Update runtime membawa semua perbaikan ini sekaligus.

Cara Update dan Checklist Operasional

Cek Versi yang Sedang Berjalan

node -v
# v22.23.3 atau lebih tua? Saatnya update.
 
# Jangan lupa cek yang dipakai di production, bukan cuma lokal
# (container, serverless, dsb.)

Update dengan nvm

nvm install 22.23.4    # atau 24.22.1 / 26.12.1
nvm alias default 22.23.4
nvm use 22.23.4

Update dengan Package Manager

# Debian/Ubuntu (NodeSource)
sudo apt update && sudo apt install nodejs
 
# Atau via fnm/asdf/mise sesuai workflow kamu

Docker

# Pastikan base image ikut di-update
FROM node:22.23.4-slim

Lalu rebuild image-nya — update package di dalam container lama tidak menolong kalau base image-nya masih lama.

Checklist Setelah Update

  1. Restart semua proses — paket yang ter-update tidak berpengaruh sampai proses yang berjalan di-restart atau diganti.
  2. Rebuild SEA / startup snapshots — wajib untuk menghilangkan bug randomUUID() (CVE-2026-106074). Snapshot lama tetap menghasilkan nilai acak yang berulang meski runtime sudah baru.
  3. Inventaris runtime — jangan lupa yang tersembunyi: image Docker turunan, fungsi serverless, embedded Node.js di aplikasi desktop (Electron punya runtime sendiri!), CI runner, dan supervisor proses.
  4. Verifikasi — cek node -v di proses yang benar-benar berjalan setelah restart.
  5. Cek versi EOL — kalau masih ada Node.js 20.x atau lebih tua di infrastruktur kamu, buat jadwal migrasi. Versi EOL selalu terdampak tapi tidak pernah dapat patch.

Kesimpulan

Rilis keamanan Oktober 2026 ini mengingatkan kita akan beberapa hal sekaligus:

  1. Satu RCE menunggu di decoder kompresi. Data terkompresi dari pihak ketiga bukan hal yang sepele — Brotli OOB write (CVE-2026-111497) adalah alasan utama untuk update hari ini.
  2. Verifikasi TLS lebih rapuh dari yang kita kira. Tiga bypass sekaligus dengan pola yang sama — "bentuk aneh tidak dikenali sebagai IP" — mengingatkan bahwa parsing alamat jaringan adalah ladang mine untuk bug keamanan.
  3. Keamanan itu rantai, bukan satu titik. Kompromi eMudhra CA membuktikan bahwa bahkan runtime yang bug-free pun butuh update rutin untuk mencabut kepercayaan yang sudah tidak sah.
  4. "Acak" belum tentu acak. Bug randomUUID() di snapshot adalah pengingat bahwa konteks eksekusi (snapshot, SEA, worker) bisa mengubah perilaku API kriptografi — dan artefak build lama harus ikut dibangun ulang.
  5. Update itu satu paket dengan restart, rebuild, dan verifikasi. Setengah update = belum update.

Kalau kamu menjalankan Node.js 22.x, 24.x, atau 26.x, jadwal kamu hari ini sederhana: update ke 22.23.4 / 24.22.1 / 26.12.1, restart semua proses, rebuild snapshot/SEA, dan verifikasi. Sepuluh bug dengan empat High — termasuk satu RCE — bukan rilis yang layak ditunda.

FAQ Singkat

Saya cuma menjalankan aplikasi internal, tidak ada yang diakses publik. Tetap harus update? Tetap. Pertama, "internal" tidak berarti aman — bypass TLS hostname dan bug DNS justru paling berbahaya di koneksi antar-service yang dianggap terpercaya. Kedua, bug Brotli tidak peduli datangnya dari publik atau dari kolega di tim sebelah yang mengunggah file. Update-nya sendiri murah; risiko menundanya yang mahal.

Apakah cukup update Node.js di laptop/CI saya? Tidak. Yang harus di-update adalah runtime yang menjalankan aplikasi di production: server, container image, fungsi serverless, dan semua turunannya. Runtime lokal yang baru tidak melindungi container yang masih pakai base image lama.

Saya pakai Node.js 20.x (EOL). Saya aman karena tidak ikut disebut? Justru sebaliknya. Advisory Node.js secara eksplisit menyatakan "end-of-life versions are always affected when a security release occurs" — artinya versi kamu tetap rentan, tapi tidak akan pernah mendapat patch. Segera migrasi ke 22.x atau 24.x (keduanya LTS).

Berapa lama sih update ini harusnya? Untuk kebanyakan tim: beberapa menit sampai beberapa jam. Update versi minor/patch LTS jarang breaking change. Yang paling lama biasanya koordinasi restart dan rebuild image — bukan update-nya sendiri.

Bug randomUUID() ini separah apa kalau aplikasi saya tidak pakai SEA? Kalau aplikasi kamu berjalan dari source biasa (atau container biasa) tanpa startup snapshot/SEA, jalur bug ini tidak terpicu. Tapi tetap update — kamu tetap kena sembilan bug lainnya.

Apakah ini ada hubungannya dengan PHP2Shell yang kemarin? Tidak ada hubungan teknis — beda ekosistem, beda root cause. Tapi keduanya dirilis di hari yang sama (21 Oktober 2026) dan mengajarkan hal yang sama: bug bisa tidur di runtime/library yang kamu percaya, dan satu-satunya jawaban yang lengkap tetap update.

Referensi

Tulisan lain