Node.js 런타임에 내장된 Google Brotli 디코더에서 경계 밖 쓰기(Out-of-Bounds Write) 취약점(CVE-2026-111497)이 공개되었습니다. Node.js는 2026년 10월 21일 22.x, 24.x, 26.x 전 지원 계열에 패치를 배포하며 원격 코드 실행 가능성을 언급하였고, 보안 업계에서는 이를 Node2Shell로 부르고 있습니다.
다만 NVD 자체 분석은 아직 진행 중이며, 공개된 PoC는 일반 빌드에서 크래시 및 제한적 메모리 노출 수준만 확인된 상태로 실제 공격 사례도 보고되지 않았습니다. 그러나 Express 5, fetch() 등 일반적인 사용 환경에서 공격 경로가 존재하고 조치가 버전 업데이트로 간단한 만큼, 선제적인 점검과 패치 적용을 권고합니다.
| 취약점 | CVE-2026-111497 (Node2Shell) |
|---|---|
| 취약점 공개일 | 2026-10-21 (Node.js 보안 공지), 2026-10-22 (CVE 레코드 공개) |
| 취약점 점수 | CVSS 4.0 9.2 (Google CNA 부여), Node.js 자체 등급 High |
| ※ NVD는 "Awaiting Analysis" 상태로 자체 점수 미산정 | |
| 설명 | Brotli 디코더(c/dec/decode.c)가 스트림 구조상 불가능한 블록 전환(block switch)을 오류가 아닌 입력 부족으로 처리하여, 잘못된 내부 상태로 디코딩을 계속 진행하는 취약점입니다. 이로 인해 버퍼 경계를 넘는 쓰기가 발생할 수 있으며, 벤더는 메모리 오염, 정보 유출, 서비스 거부 및 원격 코드 실행 가능성을 명시하고 있습니다. (CWE-787, CWE-252) |
| 취약점 영향 제품 | • Node.js 26.x: 26.12.1 미만 |
| • Node.js 24.x: 24.22.1 미만 | |
| • Node.js 22.x: 22.23.4 미만 | |
| • Node.js 25.x, 23.x, 20.x 이하 EOL 버전 전체 (패치 미제공) | |
| • Bun: 1.4.4 미만<br>• Google Brotli: 1.0.3~1.0.9, 1.1.0, 1.2.0 | |
| 악용 사례 | 2026-10-23 기준 실제 공격(ITW) 사례 없음, CISA KEV 미등재 |
| • 공개 PoC: 일반 Node.js 빌드에서는 크래시 및 제한적 메모리 노출까지만 확인, 코드 실행은 보안 기능을 약화한 테스트 환경에서만 재현 | |
| • Imperva가 공식 Node.js 24.22.0(Linux arm64) 이미지에서 RCE 재현을 주장하였으나 PoC는 비공개이며 다수 시도 끝에 성공한 제한적 결과 |
| 날짜 | 이벤트 |
|---|---|
| 📍 2026-02 | Google Brotli 업스트림에 수정 커밋(0ed4268a) 반영 |
| 📍 2026-10-21 | Node.js 보안 업데이트 배포 (22.23.4, 24.22.1, 26.12.1) 및 Google Brotli 1.0.10, 1.1.1, 1.2.1 배포 |
| 📍 2026-10-22 | Google CVE 레코드 공개 (CVSS 4.0 9.2), NVD 등재 (Awaiting Analysis) |
| 📍 2026-10-22 | Imperva, 공식 이미지 대상 RCE 재현 주장 및 "Node2Shell" 분석 공개 (PoC 비공개) |
| 📍 2026-10-23 | 국내 보안뉴스 보도 |
공식 IoC는 공개되지 않았으므로, 현 시점에서는 노출 자산 사전 식별을 우선하고 이상 행위 모니터링을 병행하는 방식을 권고합니다.
1. 노출 자산 사전 식별
node --version
docker run --rm <image> node --version
bun --version
# Express 5 / body-parser 2.x 사용 여부 (Content-Encoding: br 요청 본문 자동 해제)
npm ls express body-parser
# node:zlib Brotli 해제 함수 직접 사용 여부
grep -rnE "brotliDecompress|createBrotliDecompress" --include=*.js --include=*.ts .
fetch()를 호출하는 기능을 목록화합니다. fetch()는 Brotli 응답을 자동 해제하므로 아웃바운드 경로도 노출 대상입니다.2. 로그 기반 모니터링
Content-Encoding: br 요청을 확인합니다.