Lỗ hổng Brotli của Node.js đã chạy được mã trên bản chính thức, và Python cũng dính
CVE-2026-111497 (CVSS 9,2) nằm trong bộ giải nén Brotli bằng C mà Node.js, Bun, gói Brotli của Python và nhiều phần mềm khác cùng dùng. Imperva đã chạy được mã trên Node.js 24.22.0 bản chính thức. Nâng Node.js, nâng gói Brotli và brotlicffi trong Python, rồi build lại image.
Xem nhanh trong 1 phút
App Python của bạn chưa bao giờ import brotli, nhưng nếu gói Brotli nằm trong môi trường thì mỗi lần requests.get() gọi ra ngoài, nó vẫn có thể đang giải nén Brotli. Đó là chi tiết làm mình phải viết lại về lỗ hổng mà blog đã đưa hôm 21/10.
Hôm đó bài Node.js vá 10 lỗ hổng coi CVE-2026-111497 là chuyện của Node.js, và lúc ấy chưa ai cho thấy nó chạy được mã thật. Năm ngày sau, hai điều đã khác: có người chạy được mã trên bản Node.js chính thức, và lỗi hóa ra nằm ở thư viện Brotli viết bằng C của Google, thứ mà rất nhiều phần mềm khác cũng đóng gói bên trong. Giới bảo mật đang gọi nó bằng mấy cái tên Node2Shell, HTTP2Shell, Broccoli2Shell.
Đã có người chạy được mã
Theo The Hacker News, nhóm Red Team của Imperva chạy được mã của họ trên image Node.js 24.22.0 chính thức cho Linux arm64, không sửa gì, không cần trình gỡ lỗi. Không phải lần nào cũng trúng, họ phải thử vài lần, và Imperva không công bố mã khai thác. Bản 24.22.1 từ chối đúng dữ liệu đó.
Ngày 22/10 còn có một bản PoC công khai trên GitHub. Bản này chỉ chạy được mã trên một bản build cố tình làm yếu đi; trên bản thường nó làm Node.js sập và đọc lộ được một ít bộ nhớ. Đừng tải về chạy thử trên máy mình, mã khai thác từ tài khoản lạ hay kèm mã độc.
Đến 23/10 chưa có báo cáo tấn công thật, và lỗi chưa nằm trong danh sách KEV của CISA. Google chấm 9,2/10 theo CVSS 4.0, Node.js xếp mức cao. Một bản sập server là đủ phiền, còn đường tới chạy mã đã có người đi rồi, nên mình nghĩ không nên đợi tới lúc có tin bị khai thác hàng loạt mới vá.
Không chỉ Node.js
Lỗi nằm trong bộ giải nén Brotli bằng C, từ bản 1.0.3 tới 1.2.0. Google sửa trong mã nguồn từ tháng 2 nhưng tới 21/10 mới ra bản phát hành 1.0.10, 1.1.1 và 1.2.1. Phần mềm nào chép bộ giải nén này vào bên trong thì phải tự ra bản vá riêng.
Với người làm web và app, mấy chỗ cần để ý:
Node.js tự đóng gói Brotli, nên thư viện Brotli của hệ điều hành không liên quan. Nâng Express hay body-parser cũng không sửa được, phải nâng chính Node.js.
Bun sửa từ 1.4.4.
Python: gói Brotli sửa ở 1.2.1, brotlicffi sửa ở 1.2.1.0. Khi một trong hai gói có mặt, urllib3 và requests tự giải nén phản hồi Brotli. httpx (cài kèm httpx[brotli]), aiohttp và Scrapy cũng vậy.
Ruby gem brotli 0.9.1, extension brotli của PHP 0.21.1, .NET 8.0.33, 9.0.22, 10.0.14 đã có bản vá.
Envoy chỉ dính khi bật bộ giải nén Brotli, Istio đã có bản 1.31.2, 1.30.6, 1.29.9.
Bản port Brotli viết bằng Java, JavaScript thuần, C# và Rust không bị chạy mã.
Phần Python mới được xác nhận lỗi, chưa ai chạy được mã. Nhóm OpenSourceMalware cho một luồng dữ liệu khoảng 23 MB chạy qua cả hai bản: 1.2.0 cứ đòi thêm dữ liệu mãi, 1.2.1 từ chối ngay với mã lỗi -17. Aikido vẫn khuyên coi là việc gấp, vì cùng đoạn code C đó đã bị khai thác bên Node.js.
Khi nào app bị ảnh hưởng
Phải có dữ liệu Brotli do người khác kiểm soát đi tới bộ giải nén. Có hai đường hay gặp.
Đường thứ nhất là app gọi ra ngoài. fetch() của Node.js và requests của Python tự giải nén phản hồi. Ô “dán link để xem trước”, tính năng nhập dữ liệu từ URL, bot đọc trang web, agent AI tự lướt web là những chỗ app đi lấy dữ liệu từ server mà bạn không kiểm soát. Theo một nguồn, bỏ br khỏi header Accept-Encoding không chặn được, vì server độc vẫn có thể trả về Brotli.
Đường thứ hai là request gửi tới có Content-Encoding: br. Express 5.0.0 tới 5.3.0 và body-parser 2.0.0 tới 2.3.0 tự giải nén loại body này. Koa body parser và @fastify/compress bật giải nén request cũng vậy. Express 4, body-parser 1.x và server http trơn thì không.
Code tự gọi zlib.brotliDecompress, createBrotliDecompress hay brotli.decompress trên dữ liệu người dùng gửi lên thì khỏi bàn.
Kiểm tra app của bạn
Node.js, chạy trên máy, trên server và trong từng image:
node -vdocker run --rm <image-cua-ban> node -vnpm ls express body-parsergrep -rn "brotliDecompress\|createBrotliDecompress" --include=*.js --include=*.ts . | grep -v node_modules
Cần đạt 22.23.4, 24.22.1 hoặc 26.12.1. Còn chạy 20, 23 hay 25 thì không có bản vá, lên 22, 24 hoặc 26.
Python, chạy trong từng virtualenv và từng image:
pip show Brotli brotlicffigrep -in "brotli" requirements*.txt poetry.lock uv.lock 2>/dev/null
Có bản dưới 1.2.1 thì nâng:
pip install -U "Brotli>=1.2.1" # hoặc "brotlicffi>=1.2.1.0"
Tới 23/10, pip-audit, Dependabot và Safety chưa báo lỗi này vì cơ sở dữ liệu lỗ hổng chưa nối CVE với hai gói trên. Giờ OSV đã ghi đủ, nhưng phần lớn bản Brotli lỗi lại nằm sẵn trong runtime hay phần mềm khác chứ không phải gói Python, nên máy quét báo sạch vẫn chưa đủ. Cứ xem số phiên bản bằng tay.
Nâng xong phải khởi động lại tiến trình và build lại image. Sửa lockfile mà container đang chạy vẫn là image cũ thì chưa xong. Nếu chưa vá được ngay, chặn request có Content-Encoding: br ở reverse proxy, load balancer hay WAF. Cách này chỉ chặn được đường thứ hai, phản hồi Brotli mà app tự đi lấy thì không chặn được. Python có thêm cách tạm là gỡ hẳn Brotli và brotlicffi; requests vẫn giải nén gzip bình thường, nhưng server nào cứ trả Brotli sẽ làm app báo lỗi.
App của bạn có chỗ nào tự đi lấy dữ liệu từ link người dùng dán vào không, và bạn kiểm tra rồi thấy Brotli nằm ở đâu? Kể trong cộng đồng Vibe Code & Bảo Mật nhé.
Node.jslỗ hổngmáy chủ/anh/web/brotli-lo-hong-lan-sang-python-480.webpNode.js · lỗ hổng · máy chủ
Lo hong Brotli cua Node.js da chay duoc ma tren ban chinh thuc, va Python cung dinh CVE-2026-111497 (CVSS 9,2) nam trong bo giai nen Brotli bang C ma Node.js, Bun, goi Brotli cua Python va nhieu phan mem khac cung dung. Imperva da chay duoc ma tren Node.js 24.22.0 ban chinh thuc. Nang Node.js, nang goi Brotli va brotlicffi trong Python, roi build lai image. Node.js lo hong may chu App Python cua ban chua bao gio `import brotli`, nhung neu goi `Brotli` nam trong moi truong thi moi lan `requests.get()` goi ra ngoai, no van co the dang giai nen Brotli. Do la chi tiet lam minh phai viet lai ve lo hong ma blog da dua hom 21/10.

Hom do bai [Node.js va 10 lo hong](/nodejs-va-10-lo-hong-brotli) coi CVE-2026-111497 la chuyen cua Node.js, va luc ay chua ai cho thay no chay duoc ma that. Nam ngay sau, hai dieu da khac: co nguoi chay duoc ma tren ban Node.js chinh thuc, va loi hoa ra nam o thu vien Brotli viet bang C cua Google, thu ma rat nhieu phan mem khac cung dong goi ben trong. Gioi bao mat dang goi no bang may cai ten Node2Shell, HTTP2Shell, Broccoli2Shell.
## Da co nguoi chay duoc ma
Theo The Hacker News, nhom Red Team cua Imperva chay duoc ma cua ho tren image Node.js 24.22.0 chinh thuc cho Linux arm64, khong sua gi, khong can trinh go loi. Khong phai lan nao cung trung, ho phai thu vai lan, va Imperva khong cong bo ma khai thac. Ban 24.22.1 tu choi dung du lieu do.
Ngay 22/10 con co mot ban PoC cong khai tren GitHub. Ban nay chi chay duoc ma tren mot ban build co tinh lam yeu di; tren ban thuong no lam Node.js sap va doc lo duoc mot it bo nho. Dung tai ve chay thu tren may minh, ma khai thac tu tai khoan la hay kem ma doc.
Den 23/10 chua co bao cao tan cong that, va loi chua nam trong danh sach KEV cua CISA. Google cham 9,2/10 theo CVSS 4.0, Node.js xep muc cao. Mot ban sap server la du phien, con duong toi chay ma da co nguoi di roi, nen minh nghi khong nen doi toi luc co tin bi khai thac hang loat moi va.
## Khong chi Node.js
Loi nam trong bo giai nen Brotli bang C, tu ban 1.0.3 toi 1.2.0. Google sua trong ma nguon tu thang 2 nhung toi 21/10 moi ra ban phat hanh 1.0.10, 1.1.1 va 1.2.1. Phan mem nao chep bo giai nen nay vao ben trong thi phai tu ra ban va rieng.
Voi nguoi lam web va app, may cho can de y:
- **Node.js** tu dong goi Brotli, nen thu vien Brotli cua he dieu hanh khong lien quan. Nang Express hay body-parser cung khong sua duoc, phai nang chinh Node.js.
- **Bun** sua tu 1.4.4.
- **Python**: goi `Brotli` sua o 1.2.1, `brotlicffi` sua o 1.2.1.0. Khi mot trong hai goi co mat, `urllib3` va `requests` tu giai nen phan hoi Brotli. `httpx` (cai kem `httpx[brotli]`), `aiohttp` va Scrapy cung vay.
- **Ruby** gem `brotli` 0.9.1, extension `brotli` cua PHP 0.21.1, .NET 8.0.33, 9.0.22, 10.0.14 da co ban va.
- **Envoy** chi dinh khi bat bo giai nen Brotli, Istio da co ban 1.31.2, 1.30.6, 1.29.9.
Ban port Brotli viet bang Java, JavaScript thuan, C# va Rust khong bi chay ma.
Phan Python moi duoc xac nhan loi, chua ai chay duoc ma. Nhom OpenSourceMalware cho mot luong du lieu khoang 23 MB chay qua ca hai ban: 1.2.0 cu doi them du lieu mai, 1.2.1 tu choi ngay voi ma loi -17. Aikido van khuyen coi la viec gap, vi cung doan code C do da bi khai thac ben Node.js.
## Khi nao app bi anh huong
Phai co du lieu Brotli do nguoi khac kiem soat di toi bo giai nen. Co hai duong hay gap.
Duong thu nhat la **app goi ra ngoai**. `fetch()` cua Node.js va `requests` cua Python tu giai nen phan hoi. O "dan link de xem truoc", tinh nang nhap du lieu tu URL, bot doc trang web, agent AI tu luot web la nhung cho app di lay du lieu tu server ma ban khong kiem soat. Theo mot nguon, bo `br` khoi header `Accept-Encoding` khong chan duoc, vi server doc van co the tra ve Brotli.
Duong thu hai la **request gui toi co `Content-Encoding: br`**. Express 5.0.0 toi 5.3.0 va body-parser 2.0.0 toi 2.3.0 tu giai nen loai body nay. Koa body parser va `@fastify/compress` bat giai nen request cung vay. Express 4, body-parser 1.x va server `http` tron thi khong.
Code tu goi `zlib.brotliDecompress`, `createBrotliDecompress` hay `brotli.decompress` tren du lieu nguoi dung gui len thi khoi ban.
## Kiem tra app cua ban
**Node.js**, chay tren may, tren server va trong tung image:
```bash
node -v
docker run --rm <image-cua-ban> node -v
npm ls express body-parser
grep -rn "brotliDecompress\|createBrotliDecompress" --include=*.js --include=*.ts . | grep -v node_modules
```
Can dat **22.23.4, 24.22.1 hoac 26.12.1**. Con chay 20, 23 hay 25 thi khong co ban va, len 22, 24 hoac 26.
**Python**, chay trong tung virtualenv va tung image:
```bash
pip show Brotli brotlicffi
grep -in "brotli" requirements*.txt poetry.lock uv.lock 2>/dev/null
```
Co ban duoi 1.2.1 thi nang:
```bash
pip install -U "Brotli>=1.2.1" # hoac "brotlicffi>=1.2.1.0"
```
Toi 23/10, pip-audit, Dependabot va Safety chua bao loi nay vi co so du lieu lo hong chua noi CVE voi hai goi tren. Gio OSV da ghi du, nhung phan lon ban Brotli loi lai nam san trong runtime hay phan mem khac chu khong phai goi Python, nen may quet bao sach van chua du. Cu xem so phien ban bang tay.
**Nang xong phai khoi dong lai tien trinh va build lai image.** Sua lockfile ma container dang chay van la image cu thi chua xong. Neu chua va duoc ngay, chan request co `Content-Encoding: br` o reverse proxy, load balancer hay WAF. Cach nay chi chan duoc duong thu hai, phan hoi Brotli ma app tu di lay thi khong chan duoc. Python co them cach tam la go han `Brotli` va `brotlicffi`; `requests` van giai nen gzip binh thuong, nhung server nao cu tra Brotli se lam app bao loi.
---
App cua ban co cho nao tu di lay du lieu tu link nguoi dung dan vao khong, va ban kiem tra roi thay Brotli nam o dau? Ke trong [cong dong Vibe Code & Bao Mat](https://www.facebook.com/groups/1867387324580254) nhe.
## Nguon
- [Broccoli2Shell: Brotli decoder RCE (CVE-2026-111497)](https://broccoli2shell.com/), trang tong hop doc lap, cap nhat 26/10/2026
- [Researchers Demonstrate Node2Shell RCE Exploit on Node.js Build Using Crafted Brotli Data](https://thehackernews.com/2026/10/researchers-demonstrate-node2shell-rce.html), The Hacker News
- [Node2Shell: Node.js Brotli vulnerability allows remote code execution](https://www.aikido.dev/blog/node2shell-nodejs-brotli-rce-cve-2026-111497), Aikido, 22/10/2026
- [Python packages vulnerable to the Node2Shell Brotli flaw](https://www.aikido.dev/blog/python-packages-vulnerable-node2shell-brotli-cve-2026-111497), Aikido, cap nhat 25/10/2026
- [node2shell (CVE-2026-111497): What to Patch and How to Find Exposed Services](https://cycode.com/blog/node2shell-cve-2026-111497/), Cycode
- [HTTP2Shell (CVE-2026-111497): pip-audit Missed Brotli](https://dev.to/alanwest/http2shell-cve-2026-111497-pip-audit-missed-brotli-how-to-check-your-stack-31e3), DEV Community
- [Node.js va 10 lo hong, co loi chay ma tu xa qua bo giai nen Brotli](/nodejs-va-10-lo-hong-brotli), bai truoc tren Bao Mat AI