Node2Shell (CVE-2026-111497): Celah Brotli di Node.js Sudah Diserang, Cek Versimu
Oleh Tim APIPedia, Tim Engineering APIPedia · Terbit · 9 menit baca
Celah Brotli CVSS 9.2 masuk CISA KEV dan sudah dieksploitasi. Ini versi Node.js yang aman, cara cek, mitigasi Express 5, dan tanda serangan.

Node2Shell (CVE-2026-111497) adalah celah buffer overflow di decoder Brotli milik Google yang ikut terbawa ke Node.js, Bun, paket Python, PHP di Windows, dan .NET. CISA memasukkannya ke katalog KEV pada 27 Oktober 2026 karena sudah dieksploitasi. Kalau API kamu berjalan di Express 5 atau memakai fetch() di server, cek versi Node.js hari ini.
Celah ini dinilai 9.2 (kritis) di CVSS 4.0 oleh Google sebagai CNA. Advisory Node.js sendiri melabelinya "high". Dampak terburuknya eksekusi kode jarak jauh (RCE), tetapi yang paling sering terjadi dalam uji publik adalah proses Node.js crash. Untuk server API, crash berulang pun sudah berarti downtime.
Apa sebenarnya Node2Shell?
Akar masalahnya ada di file c/dec/decode.c pada library Brotli versi 1.0.3 sampai 1.2.0. Menurut analisis Sysdig, stream Brotli yang dirakit khusus mendeklarasikan satu tipe blok saja, lalu meminta perpindahan blok (block switch). Decoder yang belum ditambal mengabaikan error dari langkah itu (CWE-252, unchecked return value) dan menulis data di luar batas buffer (CWE-787, out-of-bounds write).
Perbaikan upstream ada di commit Brotli 0ed4268a: decoder langsung gagal bila ada block switch padahal hanya satu tipe blok yang dideklarasikan. Node.js juga menambahkan konstanta error baru, BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH.
Celah ini dikenal dengan beberapa nama: Node2Shell, HTTP2Shell, dan Broccoli2Shell. Namanya mirip PHP2Shell yang kami bahas minggu lalu, dan menurut Cyber Security News salah satu IP penyerang yang terlihat memang pernah terkait eksploitasi PHP2Shell.
Ringkasan cepat
| Item | Detail |
|---|---|
| CVE | CVE-2026-111497 (Node2Shell / HTTP2Shell) |
| Komponen | Decoder Google Brotli 1.0.3–1.2.0 (c/dec/decode.c) |
| Jenis | Out-of-bounds write (CWE-787) + unchecked return value (CWE-252) |
| Skor | CVSS 4.0: 9.2 (Google). Node.js: "high" |
| Vektor | Jaringan, tanpa login, tanpa interaksi pengguna, ada prasyarat serangan |
| Dampak | Crash (DoS), kebocoran memori, kemungkinan RCE |
| Status | Masuk CISA KEV 27 Okt 2026, tenggat federal 10 Nov 2026 |
| Node.js aman | 22.23.4, 24.22.1, 26.12.1 |
| Node.js tanpa patch | 20.x, 23.x, 25.x (sudah EOL) |
Bagaimana kronologinya?
Jarak antara patch dan serangan pertama yang terlihat cuma lima hari. Repo proof-of-concept publik pertama bahkan muncul sekitar lima jam setelah Node.js merilis perbaikan.

- 21 Oktober, 10:38 UTC: Node.js merilis 22.23.4, 24.22.1, dan 26.12.1. Sekitar 19:27 UTC, proyek Brotli merilis 1.0.10, 1.1.1, dan 1.2.1.
- 22 Oktober: CVE terbit dengan skor 9.2. Imperva Red Team mempublikasikan riset yang berhasil menjalankan kode di image resmi Node.js 24.22.0 (Linux arm64), setelah beberapa kali percobaan.
- 25 Oktober: Microsoft merilis perbaikan .NET, Visual Studio, dan PowerShell di luar jadwal Patch Tuesday.
- 26 Oktober, 15:08 UTC: ELLIO mengamati satu request eksploit berukuran 23.069.983 byte dari IP 94.154.43.7.
- 27 Oktober: CISA menambahkannya ke KEV. Entri itu tidak menyebut siapa pelakunya atau apakah dipakai ransomware.
Seberapa nyata risiko RCE-nya?
Di bagian ini sumber-sumbernya berbeda pendapat, jadi kami tulis apa adanya.
- Imperva dan Vercel melaporkan eksekusi kode pada build tertentu yang belum ditambal. Vercel juga melaporkan kebocoran memori di 22.x, 24.x, dan 26.x.
- Uji ELLIO di x86-64 menghasilkan shell di empat target, tetapi terhadap satu target bersih yang rentan rantai eksploitnya menghasilkan nol shell dari 50 percobaan dan hanya membuat proses crash. Sebagian besar dari 400 percobaan ke Express berakhir dengan worker crash.
- Offset memori untuk Node.js 24.22.0 gagal dipakai di 22.23.3 dan 26.12.0 dalam 10.000 percobaan. Artinya eksploit RCE sangat bergantung pada build yang persis sama.
- Seorang peneliti lain berpendapat dampak nyatanya adalah DoS. Klaim eksploitasi dari pihak ketiga juga belum dikonfirmasi oleh Node.js maupun Google.
Kesimpulan praktisnya sama: patch sekarang. Crash berulang pada server Express sudah cukup untuk menjatuhkan layanan, dan kalau RCE berhasil, rahasia di environment variable serta token cloud di container ikut terancam.
Siapa yang terdampak?
Node.js hanya mendekode Brotli ketika kode aplikasi atau sebuah library melakukannya terhadap data dari luar. Server http bawaan tidak mendekompresi body secara otomatis. Jadi pertanyaan utamanya: apakah kode kamu mendekompresi data Brotli yang bisa dikendalikan penyerang?

Jalur yang terpapar di Node.js
- Express 5 +
express.json(): body-parser 2.x mendekode bodybrsecara default karena opsiinflatebernilaitrue. fetch()di server: respons denganContent-Encoding: brtetap didekode, bahkan bila request mengirimAccept-Encoding: identity. Ini relevan bila server kamu memanggil URL dari pengguna (webhook, preview link, scraper).zlib.createBrotliDecompress()yang diberi input dari luar.- Framework lain yang parser body-nya mendekode
br: Koa (co-body, @koa/bodyparser, koa-body), Egg, Strapi, dan Fastify dengan @fastify/compress.
Express 4.21.2 sampai 4.22.3 (body-parser 1.x) menolak encoding selain gzip dan deflate dengan status 415, sehingga tidak lewat jalur body-parser. Tetap upgrade, karena jalur fetch() tidak bergantung pada versi Express.
Di luar Node.js
| Produk | Rentan | Versi aman |
|---|---|---|
| Node.js 26.x | < 26.12.1 | 26.12.1 |
| Node.js 24.x | < 24.22.1 | 24.22.1 |
| Node.js 22.x | < 22.23.4 | 22.23.4 |
| Node.js 20.x / 23.x / 25.x | Semua (EOL) | Tidak ada, pindah ke 22/24/26 |
| Google Brotli | 1.0.3–1.2.0 | 1.0.10, 1.1.1, 1.2.1 |
| Bun | ≤ 1.4.3 | 1.4.4 |
Python brotli / brotlicffi | < 1.2.1 / < 1.2.1.0 | 1.2.1 / 1.2.1.0 |
| PHP di Windows (ekstensi cURL, dekompresi otomatis) | Build lama | 8.5.12-1, 8.4.27-1, 8.3.36-1, 8.2.35-1 |
Alpine brotli | Versi lama | 1.2.1-r0 (1.1.1-r0 di 3.21) |
| Debian | Lihat tracker | DLA-4855-1 / DSA-6582-1 |
Catatan Debian: paket nodejs Debian memakai library Brotli sistem, jadi paket brotli juga harus ikut diperbarui.
Bagaimana cara mengecek server kamu?
Jangan uji dengan mengirim payload mirip eksploit ke server produksi. Cek versi dan jalur kode sudah cukup dan aman.
Satu jebakan penting: Node.js menambal Brotli tanpa mengubah string versinya, sehingga process.versions.brotli tetap menampilkan 1.2.0 di build yang sudah aman maupun yang belum. Patokannya versi Node.js, bukan versi Brotli.
# 1) Cek versi Node.js yang benar-benar berjalan
node -e 'const [a,b,c]=process.versions.node.split(".").map(Number);
const fix={22:[23,4],24:[22,1],26:[12,1]}[a];
if(!fix){console.log("EOL/tidak didukung, segera migrasi:",process.version);process.exit(2)}
const ok=b>fix[0]||(b===fix[0]&&c>=fix[1]);
console.log(ok?"AMAN":"RENTAN",process.version)'
# 2) Cek di dalam container yang sedang jalan (bukan tag image-nya)
docker exec <nama_container> node --version
# 3) Cek versi Express/body-parser dan jalur dekompresi di kode
npm ls express body-parser
grep -rnE "express\.json|bodyParser|createBrotliDecompress|brotli" src/
# 4) Cek Brotli di sistem dan paket Python
dpkg -l | grep -i brotli # Debian/Ubuntu
apk list --installed | grep brotli # Alpine
pip show brotli brotlicffi 2>/dev/null | grep -E "^(Name|Version)"
bun --version # bila memakai Bun
Tag seperti node:24 tidak memberi jawaban apa pun. Image lama yang masih tersimpan di cache build bisa saja berisi 24.22.0.
Apa mitigasinya?
1. Patch dan restart semuanya
- Upgrade ke Node.js 22.23.4, 24.22.1, atau 26.12.1. Kalau masih di Node.js 20, ini saatnya pindah. Panduan kami soal upgrade ke Node.js 26 LTS bisa jadi titik awal.
- Rebuild image dari base yang sudah ditambal (
docker pull node:24lalu build ulang tanpa cache). - Restart setiap service, worker, cron job, dan replika, termasuk runner CI dan fungsi serverless.
- Upgrade Bun ke 1.4.4, paket Python
brotlike 1.2.1, dan paket Brotli sistem dari distro. - Pengguna Homebrew perlu mengecek ulang, karena Homebrew sempat tertinggal saat rilis.
2. Kurangi jalur serangan sambil menunggu patch
// Express 5: tolak body terkompresi (akan dibalas 415).
// Efek samping: body gzip juga ikut ditolak, uji klien dulu.
app.use(express.json({ inflate: false }));
app.use(express.urlencoded({ extended: true, inflate: false }));
# Nginx di depan aplikasi: tolak request dengan Content-Encoding br
# (taruh di blok server/location yang meneruskan ke Node.js)
if ($http_content_encoding ~* "br") {
return 415;
}
Dua langkah di atas hanya menutup body request yang masuk. Respons yang diambil lewat fetch() tetap terpapar, dan menghapus br dari Accept-Encoding tidak mencegah server jahat mengirim Brotli. Untuk jalur itu, solusinya tetap upgrade, atau batasi fetch() hanya ke host tepercaya.
Aturan WAF hanya lapisan tambahan. Aturan baru Cloudflare untuk celah ini default-nya mode Log, jadi tidak memblokir apa pun sampai action-nya diubah. Di Azure, aturan DRS 2.2 nomor 920450 memblokir request rakitan yang dianalisis Microsoft.
3. Batasi dampak bila sampai tembus
- Jalankan Node.js sebagai user non-root.
- Jangan simpan rahasia penting di environment variable proses web. Pakai secret manager dengan akses terbatas.
- Rotasi token dan API key bila server yang rentan sempat terekspos ke internet sejak 21 Oktober.
Bagaimana mendeteksi percobaan serangan?
Sysdig menggambarkan pola pascaeksploitasi yang khas: proses Node.js crash, lalu di workload yang sama muncul eksekusi program baru, atau socket jaringan diarahkan ke stdin/stdout (reverse shell). Indikator lain yang dilaporkan:
- Request dengan
Content-Encoding: brberukuran sangat besar. Request eksploit yang dilihat ELLIO berukuran sekitar 23 MB. - IP 94.154.43.7 dan hash SHA-256 payload
7fcbdaaecd4419e2930927844f3b772668204737a4e7602a2290c991c93c5c4b. - Pemindai dengan identitas
node2shell-check/1.0dari AS44620 yang mengirim body Brotli untuk mencari host yang mendekompresi. - Worker Express yang restart berulang tanpa sebab jelas.
# Cari request Brotli di access log Nginx (butuh $http_content_encoding di log_format)
grep -E '"br"' /var/log/nginx/access.log | tail -n 50
# Cari IP yang dilaporkan ELLIO
grep -F "94.154.43.7" /var/log/nginx/access.log*
# Cari jejak crash Node.js di log systemd/container
journalctl --since "2026-10-21" | grep -iE "node.*(segfault|core dumped|SIGSEGV)"
docker ps -a --filter "status=restarting" --filter "status=exited"
Kalau kamu menemukan crash Node.js yang diikuti proses sh, bash, curl, atau wget sebagai anak proses Node, perlakukan sebagai insiden: isolasi host, ambil log, lalu rotasi kredensial.
FAQ
Apakah aplikasi Express 4 saya aman?
Express 4 dengan body-parser 1.x tidak mendekode body Brotli, jadi tidak lewat jalur itu. Namun runtime Node.js-nya tetap rentan bila ada kode lain yang memakai fetch() ke server tidak tepercaya atau createBrotliDecompress(). Upgrade runtime tetap wajib.
Kenapa process.versions.brotli masih 1.2.0 padahal sudah upgrade?
Node.js memasang perbaikan sebagai backport tanpa mengganti string versi Brotli. Pakai versi Node.js (22.23.4, 24.22.1, 26.12.1 ke atas) sebagai acuan.
Saya masih di Node.js 20. Ada patch?
Tidak. Node.js 20 sudah EOL sejak 30 April 2026 dan tidak menerima perbaikan ini, begitu pula 23.x dan 25.x. Pindah ke 22.x, 24.x, atau 26.x.
Apakah cukup memblokir Content-Encoding: br di proxy?
Belum cukup. Itu hanya menutup body request yang masuk. Respons dari server lain yang kamu ambil lewat fetch() tetap bisa memicu bug. Anggap pemblokiran di proxy sebagai penahan sementara.
Apakah celah ini juga memengaruhi PHP dan Python?
Ya, lewat library Brotli yang sama. PHP di Windows dengan ekstensi cURL dan dekompresi otomatis diperbaiki di 8.5.12-1, 8.4.27-1, 8.3.36-1, dan 8.2.35-1. Di Python, perbarui brotli ke 1.2.1 dan brotlicffi ke 1.2.1.0.
Kalau layanan kamu memanggil API pihak ketiga lewat gateway seperti APIPedia Console, pastikan juga server yang memanggilnya sudah memakai runtime yang ditambal, karena respons API pun melewati decoder yang sama.
Sumber
Topik: #keamanan #cve #nodejs #brotli #express #cisa-kev
Tentang penulis
Tim APIPedia — Tim Engineering APIPedia
Tim engineering di balik APIPedia yang membangun dan memelihara API data Indonesia - ongkir, OCR KTP, data wilayah, BMKG, hingga server MCP - dan menulis panduan integrasinya dari pengalaman langsung.