Node.js Brotli 디코더 원격 코드 실행 취약점 CVE-2026-111497
Node.js에 번들된 Google Brotli 디코더의 범위 밖 메모리 쓰기 취약점입니다. 공격자가 보낸 Brotli 데이터를 node:zlib로 압축 해제하는 애플리케이션은 원격 코드 실행까지 이어질 수 있으며, CISA KEV에 등재되었습니다. Node.js 26.12.1, 24.22.1, 22.23.4로 즉시 업그레이드하세요.
- 공지 ID
- DD-ADV-2026-0002
- 유형
- 보안
- 심각도
- Critical
- 상태
- 조치 중
- 최초 발행
- 2026년 10월 30일
- 마지막 업데이트
- 2026년 10월 30일
- CVSS
- 9.2
- CVE
- CVE-2026-111497
- 영향 받는 제품
- Node.js 26.x < 26.12.1, 24.x < 24.22.1, 22.x < 22.23.4, 20.x 이하·23.x·25.x(지원 종료)
- Google Brotli 1.0.3–1.0.9, 1.1.0, 1.2.0
- 해결된 버전
- Node.js 26.12.1, Node.js 24.22.1, Node.js 22.23.4, Brotli 1.2.1 / 1.1.1 / 1.0.10
요약 (Summary)
2026년 10월 21일 Node.js 보안 릴리스에서 CVE-2026-111497 이 공개되었습니다. Node.js에 번들된 Google Brotli 디코더의 범위 밖 메모리 쓰기(out-of-bounds write) 취약점으로, 조작된 Brotli 압축 데이터를 node:zlib로 압축 해제하면 프로세스 메모리가 손상됩니다. 그 결과 프로세스 크래시, 프로세스 메모리 노출, 원격 코드 실행으로 이어질 수 있습니다. 보안 업계에서는 Node2Shell, Brotli2Shell 등으로 부릅니다.
- 심각도: Node.js 프로젝트는 High로 분류했고, Brotli의 CNA인 Google은 CVSS v4.0 9.2(Critical) 를 부여했습니다.
- 악용 현황: GitHub에 공개 PoC가 있으며, 실제 공격 트래픽이 보고되었습니다. CISA는 2026년 10월 27일 이 취약점을 KEV(Known Exploited Vulnerabilities) 카탈로그에 추가했습니다.
- 조치: 지원 중인 Node.js 버전으로 즉시 업그레이드하는 것이 유일한 근본 조치입니다. Node.js는 공식 우회 방법을 제공하지 않습니다.
Cloudera 고객은 Cloudera 제품 관점의 공지 CCA-2026-1003과 TSB 2026-1007도 함께 확인하세요(패스워드 필요).
취약점 상세 (Details)
Node.js 공지에 따르면, 잘못된 블록 전환(block switch)이 영구적인 형식 오류가 아니라 "입력이 더 필요하다"는 일시적 상태로 보고되는 결함이 있었습니다. 그 때문에 스트리밍 디코더가 8바이트 크기의 내부 버퍼에 입력 바이트를 계속 덧붙였고, 버퍼 끝을 넘어 메모리를 쓰게 됩니다.
- 원인 위치: 업스트림 google/brotli 디코더. 수정은 2026년 2월 27일 업스트림에 커밋되었지만 당시에는 릴리스나 공지가 없었고, 10월 공개 시점에 Brotli 1.2.1·1.1.1·1.0.10이 나왔습니다.
- 보고자: OpenAI Codex Security, Khai Tran, Sylvie Mayer (Node.js 공지 기준)
그림으로 보는 동작 원리

그림 1. 잘못된 블록 전환을 처리하는 두 경로. Node.js 공식 보안 공지를 바탕으로 작성한 개념도이며, 메모리 칸은 실제 주소·배치를 재현한 것이 아닙니다. 그림을 누르면 확대할 수 있습니다.
그림은 동일한 잘못된 입력을 정상적으로 거부하는 경우와 취약한 디코더가 계속 처리하는 경우를 비교합니다.
- 입력이 디코더에 도달합니다. 애플리케이션이 공격자가 제어하는 Brotli 데이터를
node:zlib로 압축 해제할 때 취약한 처리 경로에 진입할 수 있습니다. - 오류의 종류를 잘못 구분합니다. 스트리밍 처리에서는 입력이 아직 덜 도착한 상태와, 추가 데이터를 받아도 유효해지지 않는 형식 오류를 구분해야 합니다. 이 결함은 잘못된 블록 전환을 후자가 아닌 전자로 보고합니다.
- 입력 바이트를 계속 덧붙입니다. 디코더가 중단하지 않고 8바이트 내부 버퍼에 입력을 추가하다가 버퍼 끝을 넘어 씁니다. 여기서 8바이트는 디코더 내부 버퍼 크기이며, HTTP 요청 본문이나 압축 해제 결과의 허용 크기가 아닙니다.
- 메모리 손상이 발생합니다. 손상된 영역과 실행 환경·공격 조건에 따라 크래시, 프로세스 메모리 노출 또는 원격 코드 실행으로 이어질 수 있습니다. 세 결과가 순서대로 발생하거나, 모든 잘못된 입력이 곧바로 코드 실행에 성공한다는 뜻은 아닙니다.
운영 점검에서는 외부 입력 → Brotli 압축 해제 → 실행 중인 Node.js 경로를 따라가며 확인해야 합니다. 아래 영향 범위 표의 요청·응답·파일 처리 중 어떤 경로가 실제로 디코더를 호출하는지 확인하고, 해당 워크로드에 수정 버전을 적용하세요.
영향 범위
공격자가 제어할 수 있는 Brotli 데이터를 애플리케이션 또는 그 라이브러리가 압축 해제하는 경우 노출됩니다. 디코더가 들어 있다는 사실만으로 곧바로 악용 가능하다는 뜻은 아닙니다.
| 경로 | 예시 |
|---|---|
| 인바운드 요청 | Content-Encoding: br 요청 본문을 압축 해제하는 서버·미들웨어, Brotli 파일 업로드 처리 |
| 아웃바운드 응답 | 애플리케이션이 외부 서버에서 가져온 Brotli 응답을 압축 해제하는 경우(fetch(), HTTP 클라이언트 등) |
| 데이터 처리 | 외부에서 받은 .br 파일·메시지를 zlib.brotliDecompress 등으로 해제하는 배치·워커 |
아웃바운드 응답 경로는 WAF로 막을 수 없습니다. 런타임 패치만이 이 경로를 막습니다.
Brotli 디코더는 Node.js 외에도 Bun, .NET, Python brotli·brotlicffi 패키지, Envoy·Istio, brotli4j, FFmpeg, Apache Arrow, ClickHouse, 운영체제 패키지 등에 포함되어 있습니다. 해당 제품을 쓰고 있다면 각 공급업체 공지를 확인하세요.
영향받는 버전 및 수정 버전 (Affected / Fixed Versions)
| 릴리스 라인 | 영향받는 버전 | 수정 버전 |
|---|---|---|
| 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 | 전체 | 수정 없음(지원 종료) → 지원 라인으로 이전 |
| Google Brotli | 1.0.3–1.0.9, 1.1.0, 1.2.0 | 1.0.10, 1.1.1, 1.2.1 |
같은 Node.js 보안 릴리스에서 함께 수정된 주요 취약점은 다음과 같습니다.
| CVE | 내용 | 심각도 |
|---|---|---|
| CVE-2026-105482 | dns.resolve가 NUL 문자가 든 이름을 잘라 처리 | High |
| CVE-2026-105483 | 전각 숫자로 쓴 IP에서 TLS 인증서 호스트명 검증 우회 | High |
| CVE-2026-106069 | IP 주소로 느슨하게 해석되는 호스트에서 TLS 인증서 호스트명 검증 우회 | High |
| CVE-2026-105481 | keep-alive 소켓이 요청 전송 전에 쓰인 응답을 처리 | Medium |
| CVE-2026-106072 | 비정규 IPv4 호스트명에서 DNS SAN으로 IP 엔드포인트를 인증 | Medium |
| CVE-2026-106074 | crypto.randomUUID()·randomInt() 엔트로피 캐시가 스냅샷·SEA에 저장 | Medium |
이 밖에 Low 3건과 c-ares, OpenSSL, SQLite, Undici, eMudhra 중간 CA 인증서 관련 의존성 업데이트가 포함되어 있습니다. 전체 목록은 Node.js 공지를 참고하세요.
Google Brotli 업스트림 패치
Google Brotli는 2026년 10월 21일 보안 수정 버전을 이미 배포했습니다. 공식 릴리스 노트 세 곳 모두 CVE-2026-111497 수정을 명시합니다.
코드에서 무엇이 바뀌었나?
업스트림 수정 커밋 0ed4268은 c/dec/decode.c와 c/include/brotli/decode.h를 변경했습니다. 핵심은 실패 원인을 구분하고, 호출부까지 그 상태를 전달하는 것입니다.

그림 2. 업스트림 코드 변경을 요약한 패치 전후 비교. 그림의 SUCCESS 등 상태명은 BROTLI_DECODER_ 접두사를 생략했습니다. 여기서 성공은 해당 내부 처리 단계의 성공을 뜻합니다. 그림을 누르면 확대할 수 있습니다.
| 변경 지점 | 패치 전 | 패치 후 |
|---|---|---|
DecodeBlockTypeAndLength() 반환값 | BROTLI_BOOL로 성공·실패만 반환 | BrotliDecoderErrorCode로 성공·입력 부족·형식 오류 구분 |
| 잘못된 블록 전환 | 입력 부족과 동일하게 BROTLI_FALSE 반환 | BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH 반환 |
| 실제 입력 부족 | BROTLI_FALSE 반환 | BROTLI_DECODER_NEEDS_MORE_INPUT 반환 |
| 블록 전환 호출부 | 일부 빠른 처리 경로에서 반환값 무시 | BROTLI_SAFE_WITH_STATUS로 상태 확인·전달 |
| 오류 코드 정의 | -17은 예약된 값 | BLOCK_SWITCH 형식 오류에 -17 할당 |
새 호출 매크로는 일반 경로와 빠른 처리 경로 모두에서 결과를 확인합니다. 성공이 아니면 현재 상태를 저장하고 상위로 반환하므로, 형식 오류를 추가 입력 대기로 잘못 이어가는 흐름을 끊습니다. 실제 입력이 부족한 경우에는 입력을 기다리는 정상 동작을 유지합니다. 이 커밋은 내부 버퍼를 늘리는 수정이 아닙니다.
운영 환경에는 어떻게 적용하나?
Google Brotli의 수정 릴리스와 이를 내장한 제품의 수정 릴리스는 따로 확인해야 합니다. Node.js 사용자는 앞의 Node.js 수정 버전을 적용하고, Brotli를 직접 빌드·포함하는 애플리케이션은 수정된 소스로 다시 빌드해 배포합니다. OS 패키지로 설치했다면 배포판의 보안 업데이트를 확인하세요.
특히 제품이 자체 Brotli 사본을 포함하면 OS 라이브러리만 교체해서는 그 사본이 바뀌지 않습니다. 예를 들어 Brotli4j는 Brotli 1.2.1을 포함한 1.24.0에서 수정되었으며, 공식 공지는 brotli4j와 사용하는 native-* 아티팩트를 함께 업데이트하도록 안내합니다. Brotli4j 공식 보안 공지
권고 조치 (Action Required)
- Node.js 업그레이드 — 26.12.1, 24.22.1, 22.23.4 이상으로 올립니다. 20.x 이하를 쓰고 있다면 22.x 또는 24.x로 이전합니다.
- 실행 중인 워크로드까지 교체 — 서버에 설치된 Node.js만 바꾸는 것으로 끝나지 않습니다.
- 컨테이너는 패치된
node베이스 이미지로 다시 빌드하고 재배포합니다. - CI 러너, 서버리스 런타임, 개발 PC, 사내 도구도 함께 확인합니다.
- 서비스를 재시작한 뒤
node -v로 실제 실행 버전을 확인합니다.
- 컨테이너는 패치된
- Brotli를 번들한 다른 구성 요소 점검 — Python
brotli·brotlicffi, Bun, Envoy·Istio, 정적 링크된 Brotli 라이브러리는 Node.js 업그레이드로 해결되지 않습니다. 의존성 lock 파일을 갱신하고 공급업체 업데이트를 적용합니다. - 즉시 업그레이드가 어려운 경우의 보완 통제(compensating controls)
- 신뢰할 수 없는 Brotli 입력 경로 제한·비활성화: 외부 입력을 Brotli로 압축 해제하는 기능을 끄거나 신뢰된 출처로 제한합니다.
- WAF·리버스 프록시 필터링: 영향받는 서비스로 향하는
Content-Encoding: br요청을 차단합니다. 다만 아웃바운드 응답과 업로드 파일 안의 Brotli 데이터는 막지 못합니다. - 아웃바운드 Brotli 응답 처리 끄기: 외부 응답을 받는 HTTP 클라이언트가 Brotli 인코딩을 받지 않도록 구성합니다.
- 최소 권한·격리: Node.js 프로세스를 최소 권한으로 실행하고 컨테이너 수준에서 격리합니다.
- 침해 징후 모니터링 — 예상치 못한 Node.js 프로세스 크래시, 비정상적인 메모리 사용, Node.js 프로세스가 띄운 셸·외부 연결을 확인합니다.
중요: 보완 통제는 노출을 줄일 뿐 취약점을 없애지 않습니다. KEV에 등재된 만큼 패치를 최우선으로 진행하세요.
참고 자료 (References)
- Google Brotli: v1.2.1, v1.1.1, v1.0.10
- Google Brotli: 수정 커밋 0ed4268 — Detect and report invalid stream earlier
- Brotli4j: CVE-2026-111497 보안 공지
- Node.js: Wednesday, October 21, 2026 Security Releases
- NVD: CVE-2026-111497
- CISA: CISA Adds Two Known Exploited Vulnerabilities to Catalog (2026-10-27)
- Rapid7: CVE-2026-111497: Critical out-of-bounds write in the Node.js Brotli decoder
- Tenable: Brotli2Shell FAQ
- Vercel: Node.js security advisory: Brotli decoder RCE (CVE-2026-111497)
- Help Net Security: Brotli bug reaches far beyond Node.js
변경 이력 (Change Log)
| 날짜 | 변경 사항 |
|---|---|
| 2026-10-30 | 최초 발행 |
| 2026-10-30 | 정상 오류 처리와 취약한 디코더의 동작 비교 도식, 내부 버퍼 및 메모리 손상 과정 설명 추가 |
| 2026-10-30 | Google Brotli 공식 수정 릴리스·코드 변경·제품별 적용 설명과 패치 전후 비교 도식 추가 |