Node.js 2026년 10월 보안 수정 사항 및 Brotli RCE

지원 종료(EOL)된 PHP용 php2shell 패치(CVE-2026-109618 및 CVE-2026-109619)가 출시되었습니다. 수요가 많아 평소보다 영업팀의 답변이 늦어지고 있으므로, 패치된 패키지를 가장 빠르게 확보하려면 온라인에서 Runtimes용 ELS를 구매하시기 바랍니다 (새 탭에서 열림). 패치 FAQ 읽어보기

이 블로그 글의 AI 요약으로 바로 가기

  • Perplexity를 사용하여 이 게시물을 요약해 주세요
  • Gemini로 이 게시물을 요약해 주세요

10월 Node.js 수정 사항을 반영한 ELS 빌드가 곧 제공될 예정입니다

영향을 받는 지원 종료 Node.js 제품군에 대한 수정된 빌드는 향후 24~48시간 내에 ELS for Runtimes 저장소에 공개될 예정이며, 각 제품군에 적용되는 10월 21일자 CVE를 모두 포함할 것입니다.

런타임용 ELS 상태: 저희 팀은 현재 지원이 종료된 해당 버전에 대한 패치를 마무리하고 있으며, 적용 시기는 버전과 플랫폼에 따라 다소 차이가 있습니다. 업데이트는 동일한 경로를 통해 제공됩니다. yum, apt 또는 apk 이미 사용 중인 워크플로우이며, 빌드는 다음 위치에 있습니다. /opt/alt/ 호스트에 설치된 다른 Node.js 버전과 병행하여 사용할 수 있습니다. 패키지가 설치되면 모든 Node.js 프로세스를 재시작하도록 계획하십시오.

런타임용 ELS 다운로드 →

요약

전체 버전으로 이동 ↓

사건 개요: 2026년 10월 21일, Node.js는 사전 경고를 발령한 지 일주일 만에 지원 중인 22.x, 24.x, 26.x 세 가지 버전에 대한 보안 업데이트를 배포했습니다. 총 10건의 CVE가 발견되었으며, 그중 4건은 ‘높음(High)’ 등급으로 분류되었습니다. 이 섹션으로 이동 →

가장 심각한 취약점의 영향: CVE-2026-111497은 Node.js에 포함된 Brotli 디코더에서 발생하는 범위를 벗어난 쓰기(out-of-bounds write) 취약점으로, 해당 보안 권고문에 따르면 원격 코드 실행이 가능하다고 합니다. 패치가 적용되지 않은 빌드에서 공격자가 제어하는 Brotli 데이터를 압축 해제하는 모든 프로세스는 취약점에 노출되며, 이러한 상황이 발생하기 위해 코드가 Brotli를 직접 호출할 필요는 없습니다. 이 섹션으로 이동 →

실제로 상황이 얼마나 심각한지: 최초의 공개 개념 증명(PoC)은 의도적으로 취약점을 유발한 빌드에서만 코드 실행에 성공했는데, 이로 인해 해당 권고문의 표현만큼 시급해 보이지 않았다. 그러자 임퍼바(Imperva)의 레드팀이 다음과 같은 내용을 공개했다. Node2Shell, 다음을 통해 공식 Node.js 24.22.0 이미지에서 코드 실행이 이루어지는 것을 보여줍니다. fetch() 그리고 Express 5 요청 파싱. 10월 22일 현재, 실제 환경에서 악용된 사례는 보고된 바가 없습니다. 이 섹션으로 이동 →

영향을 받는 대상: 해당 계열의 수정된 버전보다 오래된 모든 22.x, 24.x 또는 26.x 릴리스와, Node.js에서 더 이상 패치를 제공하지 않는 지원 종료(EOL) 계열입니다. 아래의 CVE 표에는 어떤 CVE가 어떤 계열에 영향을 미치는지 나와 있습니다. 이 권고문은 지원 종료된 버전은 항상 영향을 받는다는 기존 경고를 재차 강조하며, Node.js 20, 18, 16, 14 및 12 버전은 업스트림으로부터 어떠한 지원도 받지 못한다고 밝혔습니다. 이 섹션으로 이동 →

현재 상황: 22, 24, 26 버전에 대한 업스트림 수정 사항이 공개되었습니다. Vercel의 WAF는 플랫폼 내 프로젝트에 대한 인바운드 공격 경로를 차단하지만, 코드가 외부에서 가져오는 응답까지는 차단하지 않습니다. 영향을 받는 지원 종료(EOL) 라인에 대한 ELS for Runtimes 빌드는 향후 24~48시간 내에 제공될 예정입니다.

오늘 해야 할 일: 지원되는 라인에 패치를 적용하고, 지원이 종료된 라인은 해당 라인용 빌드가 적용되는 즉시 고정된 ELS 빌드로 이동시킨 다음, 모든 것을 재시작하세요. 실행 중인 프로세스는 메모리에 이전 디코더를 유지하기 때문입니다. 현재 실행 중인 프로세스를 확인하려면:

ps -eo pid,lstart,args | grep -E '[n]ode( |$)'

이 섹션으로 이동 →

자세한 내용

대부분의 Node.js 보안 작업은 한 단계 위에서 이루어집니다. Dependabot이 풀 리퀘스트를 생성하면, npm audit 일단 조용해지면, 아무도 모든 것이 작동하는 기반이 되는 바이너리에 대해 단 1초도 생각하지 않습니다. 하지만 런타임 자체에도 CVE가 존재하는데, 10월 21일, 그중 가장 심각한 문제가 바로 여러분의 앱이 인터넷에서 직접 불러오고 있을지도 모르는 디코더의 메모리 손상인 것으로 밝혀졌습니다.

22일, 24일, 26일 중 어느 날이든, 패치 내용은 지루할 뿐입니다. 패치 버전을 올리고, 함대를 업데이트한 뒤, 다음으로 넘어가면 됩니다.

시스템의 일부가 여전히 Node.js 18이나 20을 사용 중일 때는 지루함이 훨씬 덜합니다. 네이티브 애드온이 그보다 최신 버전에서는 빌드되지 않거나, 프레임워크 마이그레이션이 분기마다 계속 미뤄지기 때문이죠. 해당 코드에는 수정 사항이 적용되기 전 버전의 Brotli 디코더가 포함되어 있어, 어떤 패치도 적용받지 못합니다. 이 글의 대부분은 바로 그 격차에 관한 내용입니다.

10가지 CVE와 모두가 화제로 삼고 있는 그 하나

이 프로젝트는 평소와 마찬가지로 일주일 전에 사전 공지를 내보냈습니다. 10월 14일, 앙투안 뒤 하멜(Antoine du Hamel)은 oss-security 메일링 리스트에 사전 경고를 게시하며, 10월 21일 또는 그 직후에 새로운 22, 24, 26 버전이 출시될 것이며, 가장 높은 심각도 등급은 ‘High’라고 밝혔습니다. 구성 요소 이름이나 CVE 번호는 언급되지 않았는데, 이는 Node.js에서는 일반적인 일입니다. 릴리스는 예정대로 진행되었습니다.

CVE-2026-111497이 주요 제목입니다. 이 보안 권고문은 OpenAI Codex Security의 Khai Tran과 Sylvie Mayer가 취약점을 보고했으며, Matteo Collina와 Antoine du Hamel이 수정 조치를 제공했다고 밝히고 있습니다. 초기 보도 몇 건에서는 Collina가 이 취약점을 발견했다고 전했으나, 보안 권고문에서는 그를 수정 담당자로 명시하고 있습니다. 패치 자체는 업스트림 Brotli 커밋 0ed4268a에서 선별한 것으로, “무효한 스트림을 더 일찍 감지하고 보고한다”는 매우 간결한 메시지를 담고 있습니다.

해당 커밋의 시기가 다소 의아합니다. The Hacker News에 따르면, 이 변경 사항은 2026년 2월에 Brotli 소스 코드에 처음 반영되었지만, 10월 21일 Brotli 1.2.1, 1.1.1 및 1.0.10이 출시되면서 비로소 보안 릴리스에 포함되었습니다. 즉, 메모리 안전성 버그에 대한 수정 코드가 수개월 동안 공개 저장소에 방치되어 있었으며, 이 버그를 발견한 공로는 AI 보안 도구에 돌아갔습니다. 앞으로 이러한 사례가 훨씬 더 자주 나타날 것이며, 예고 없이 업스트림에 커밋된 코드가 실제 악용 가능한 익스플로잇으로 발전하기까지 걸리는 시간도 점점 더 짧아질 것으로 예상됩니다.

나머지 세 가지 ‘고위험’ 취약점은 모두 이름 처리와 관련이 있습니다. CVE-2026-106069는 호스트가 IP 주소로 대략적으로만 확인될 때 TLS 인증서가 호스트 이름 검증을 통과하도록 합니다. CVE-2026-105483은 IP 주소가 전각 숫자로 작성되었을 때 작동하는 별도의 우회 취약점입니다. 이 취약점은 24.x 및 26.x 버전에만 영향을 미치며, The Hacker News는 해당 취약점을 수정하는 커밋에서 버그를 ‘낮은 심각도’이자 ‘악용하기 어렵다’고 기술하고 있음에도 불구하고, 보안 권고문에서는 이를 ‘높은 심각도’로 평가하고 있다고 지적합니다. CVE-2026-105482는 dns.resolve(), 이 경우 NUL 바이트가 포함된 이름이 잘릴 수 있어, 코드에서 유효성을 확인한 이름과 실제로 쿼리된 이름이 일치하지 않을 수 있었습니다. 패치된 버전은 리졸버 입력에서 NUL 바이트를 아예 거부합니다.

‘중간’ 및 ‘낮음’ 등급의 항목들은 범위가 더 좁지만 무시할 수 있는 것은 아닙니다. CLI나 도구를 단일 실행 파일 형태로 배포하는 모든 사용자에게 주목할 만한 항목은 CVE-2026-106074입니다. 뒤편에 있는 엔트로피 캐시는 crypto.randomUUID() 그리고 crypto.randomInt() 이 값들은 시작 스냅샷과 SEA에 저장되고 있었기 때문에, 동일한 바이너리에서 실행된 모든 프로세스는 동일한 “무작위” 값을 생성했습니다. 해당 UUID를 토큰이나 논스로 사용하는 모든 요소는 검토가 필요합니다.

CVE 위험도 문제 영향을 받는 노선
111497 높음 번들로 제공되는 Brotli 디코더의 범위를 벗어난 쓰기 작업으로 인해 원격 코드 실행이 가능해집니다. 26.x, 24.x, 22.x
106069 높음 호스트가 대략적으로 IP 주소로 확인될 때 발생하는 TLS 호스트명 우회 26.x, 24.x, 22.x
105483 높음 IP 주소가 전각 숫자로 표기되었을 때 TLS 호스트명 우회 26.x, 24.x
105482 높음 dns.resolve() NUL 문자가 포함된 이름을 잘라냅니다 26.x, 24.x, 22.x
105481 Medium Keep-alive 소켓은 요청이 전송되기 전에 작성된 응답을 처리합니다. 26.x, 24.x, 22.x
106072 Medium 비표준 IPv4 호스트명을 사용하면 인증서의 DNS SAN을 통해 IP 엔드포인트를 인증할 수 있습니다. 26.x, 24.x, 22.x
106074 Medium randomUUID() 그리고 randomInt() 시동 스냅샷 및 SEA에 저장된 캐시 26.x, 24.x, 22.x
106070 낮음 ZipFile은 헤더 유효성 검사 실패 시 공격자가 제어하는 접두사 바이트를 반환합니다. 26.x
106071 낮음 와일드카드 조회를 통한 파일 시스템 권한 모델의 과도한 권한 부여 26.x
106073 낮음 다음 방법을 통한 권한 모델 우회 fs.realpathSync 26.x, 24.x, 22.x

이번 릴리스에서는 세 가지 제품군 모두에서 c-ares, undici 및 번들된 CA 인증서를 업데이트하고, 22.x 및 24.x 버전의 OpenSSL과 22.x 버전의 SQLite도 업데이트합니다. 인증서 변경 사항이 가장 주목할 만한 부분입니다. Node.js는 Mozilla의 루트 목록을 사용하지만 기본적으로 인증서 해지 확인을 수행하지 않기 때문에, 이번 달에 보안 침해로 보고된 8개의 eMudhra 중간 인증서를 기반으로 구축된 인증서 체인은 이번 릴리스 직전까지 계속 유효한 것으로 확인되었습니다. 패치된 빌드에는 해당 키들에 대한 컴파일된 차단 목록이 추가되었으며, 이는 Go가 자체 수정본에 포함시킨 해시와 동일합니다. 두 가지 주의 사항이 있습니다. 업그레이드 이전에 시작된 TLS 세션은 타임아웃될 때까지 재검증되지 않으며, 지원이 종료된 라인에는 차단 기능이 전혀 적용되지 않습니다.

Brotli가 허락도 없이 어떻게 여러분의 프로세스에 침투하는가

Node.js는 자체적으로 Brotli를 디코딩하지 않습니다. 프로세스 내의 어떤 요소가 이를 요청해야 하는데, 사용자가 눈치채지 못하는 사이에도 많은 요소가 이를 요청합니다.

아웃바운드 트래픽이 가장 큰 문제입니다. 내장된 fetch() 다음 내용을 포함하는 응답을 압축 해제합니다. Content-Encoding: br 자동으로 수행되며, 이를 해제할 수 있는 호출자 옵션은 없습니다. 현재 버전의 axios, node-fetch 및 got도 기본적으로 동일하게 동작합니다. 따라서 자신이 제어하지 않는 URL을 요청하는 모든 서비스, 즉 웹훅 송신기, 링크 미리보기 워커, 스크레이퍼, 웹 페이지를 프롬프트로 가져오는 AI 에이전트 등이 해당 범주에 포함됩니다. Vercel의 공지 간과하기 쉬운 또 다른 원인을 추가합니다. 자체 호스팅형 Next.js는 이미지 최적화 과정에서 Brotli 응답을 차단하지 않으므로, 이 문제를 해결하려면 Next.js 설정을 건드리지 말고 Node.js를 업그레이드해야 합니다.

인바운드는 두 번째 경로입니다. Express 5의 바디 파서(body-parser 2.x)는 기본적으로 Brotli로 압축된 요청 본문을 해제하므로, 다음을 사용하는 API는 express.json() 요청한 적이 없는 Brotli 본문을 압축 해제합니다. Express 4의 body-parser 1.x는 Brotli 본문을 처리하지 못하며, 415 오류 코드와 함께 이를 거부합니다. 단순한 http 서버는 요청 본문을 수신하는 것만으로는 이를 디코딩하지 않습니다. 그리고 코드가 직접 호출하는 방식도 있는데, zlib.brotliDecompress() 또는 createBrotliDecompress() 업로드된 파일, 아카이브 또는 캐시된 아티팩트에 대해.

긴급도를 빠르게 판단하는 방법입니다. Express 5에서 인터넷에 노출되는 모든 서비스나 임의의 URL을 조회하는 서비스는 오늘 바로 패치를 적용해야 합니다. 사용자 소유의 백엔드와만 통신하고, 사용자 정의 압축 해제 미들웨어가 없으며, 직접적인 zlib Brotli는 외부 데이터를 참조하므로 목록에서 순위를 조금 더 낮게 책정할 수 있습니다. 하지만 나머지 9개의 CVE는 사용 중인 Express 버전에 상관없이 영향을 미치므로, 이번 주에 업데이트를 진행해야 합니다. 해당 권고문에는 임시 해결책이 제시되어 있지 않습니다. 설정 inflate: false 바디 파서, axios 또는 got에서 압축 해제 기능을 비활성화하거나, 거부하는 경우 Content-Encoding: br 주식 대리 투표 시 몇 시간 동안은 위험 노출을 줄일 수 있지만, fetch() 끄기 버튼이 없으며, 이러한 조치들 중 어느 것도 근본적인 해결책이 되지 못합니다.

‘연구실의 호기심’에서 ‘스톡 이미지’로, 단 하루 만에

이 취약점 관련 소식은 순식간에 퍼져 나갔다. 10월 22일 공개 개념 증명(PoC)이 등장했는데, ‘더 해커 뉴스( The Hacker News)’에 따르면 이는 의도적으로 취약하게 조작된 테스트 빌드에서만 코드 실행에 성공한 것으로 나타났다. 표준 빌드의 경우, 해당 작성자는 시스템 충돌과 제한적인 메모리 읽기 현상만 보고했다. 이 내용을 보고 단순히 다음 스프린트로 티켓을 미루는 것도 쉬운 일이었을 것이다.

같은 날, 임퍼바(Imperva)의 레드팀이 다음 내용을 발표했다. Node2Shell. 디버거나 계측된 바이너리가 없는, 공식 Node.js 24.22.0 Linux arm64 이미지를 실행하는 새로 설치된 컨테이너에서, 요청 응답이나 요청 본문으로 전달된 Brotli 데이터로 인해 애플리케이션이 해당 데이터와 함께 제공된 코드를 실행하는 현상이 발생했습니다. 연구진은 다음을 통해 이 현상을 재현했습니다. fetch() 그리고 Express 5.0.0부터 5.3.0까지, 다음을 사용하여 raw() 그리고 json() 파서들. 동일한 입력 데이터가 24.22.1에서 반송되었습니다. 해당 환경에서 여러 번 시도해야 했고, arm64 아키텍처만 테스트했기 때문에 버튼 하나만 누르면 바로 되는 수준은 아니지만, “실험실에서만 작동한다”는 말과는 거리가 멉니다.

트라이아지(Triage) 팀이 첫 번째 개념 증명(PoC)을 근거로 이 문제를 보류 처리했다면, 해당 문제를 재개하십시오. 또한 임퍼바(Imperva)는 압축 해제 중 예상치 못한 프로세스 종료가 조사 우선순위를 정하는 데 도움이 될 수 있다고 지적하지만, 크래시나 디코더 오류만으로는 악용 여부를 신뢰할 수 있는 지표가 되지 못한다고 밝혔습니다. 10월 22일 현재, 실제 환경에서 악용된 사례는 보고된 바 없으며, CVE-2026-111497은 CISA의 ‘알려진 악용 취약점’ 목록에 포함되어 있지 않습니다.

상류 쪽의 선들은 서로 닿지 않는다

Node.js 보안 권고문에는 항상 반복되는 경고가 포함되어 있으며, 이번 권고문도 이를 재차 강조하고 있습니다. 보안 패치가 출시될 때마다 지원 종료된 버전은 항상 영향을 받습니다. 이는 정책상의 명시 사항일 뿐, 개별 CVE에 대한 테스트 결과가 아닙니다. 확실한 점은 Brotli 관련 수정 사항이 10월 21일에야 Node.js에 반영되었기 때문에, 지원이 종료된 업스트림 릴리스 중 이 수정 사항을 포함하고 있는 것은 없다는 것입니다. Node.js 20은 2026년 4월 30일, 18은 2025년 4월 30일, 16은 2023년 9월 11일, 14는 2023년 4월 30일, 12는 2022년 4월 30일에 지원 종료됩니다. 이들 버전 중 어느 것도 이에 대한 릴리스를 받지 못합니다. Vercel도 이에 대해 단호한 입장을 보였습니다. 자사 플랫폼에서 여전히 Node.js 20에 고정된 프로젝트는 20 버전에 대한 수정 사항이 제공되지 않으므로 22 또는 24 버전으로 전환하고 다시 배포해야 합니다.

Brotli 버그의 기원은 얼마나 오래전으로 거슬러 올라갈까요? Brotli는 Node.js 10.x 및 11.x 시절부터 포함되어 왔으며, Brotli 프로젝트 팀은 이 수정 사항을 1.0 브랜치까지 소급 적용했습니다. 이는 취약한 디코더 로직이 지난 봄에 새로 도입된 것이 아니라 오래전부터 존재해 왔음을 시사하는 강력한 단서입니다. Node.js 16 및 그 이전 버전에는 전역 변수가 없습니다. fetch(), 하지만 axios와 got은 여전히 동일한 zlib 디코더에 Brotli 응답을 전달하며, 직접 zlib 모든 회선에서 통화 기능은 동일하게 작동합니다.

문제를 일으키는 설치 사례는 대개 사람들이 흔히 생각하는 Node.js 서버와는 거리가 멉니다. 이미지 처리 애드온이 18 버전에서는 더 이상 컴파일되지 않아 Node 16에 고정된 빌드 컨테이너라든가, 2022년에 누군가가 단일 바이너리 파일로 배포한 내부 관리 도구 같은 것들이죠. 웹 콘솔에 Node 14가 탑재된 벤더 어플라이언스. 유지보수자가 자리를 떠난 하나의 종속성 때문에 Node 18에 고정된 40개의 서비스를 운영하는 결제 팀을 상상해 보세요. 이 팀은 패치가 제공되지 않은 RCE(원격 코드 실행) 보안 권고문을 읽고 있습니다. 금요일까지 40개의 서비스를 마이그레이션할 수 있는 사람은 아무도 없습니다.

이것이 바로 ELS for Runtimes가 메우는 공백입니다. TuxCare는 지원 종료된 Node.js 버전에 대한 보안 패치를 제공하므로, 해당 제품군의 빌드가 출시되면 18 버전으로 고정된 서비스는 긴급 마이그레이션 대신 패키지 업데이트를 통해 이번 달의 패치를 받을 수 있습니다. 물론 마이그레이션은 여전히 수행되어야 하며, Node.js의 지원 종료 일정은 변경되지 않습니다. ELS를 사용하면, 보안 권고 기관이 정한 일정이 아닌 귀사 팀이 직접 정한 일정에 따라 마이그레이션이 진행됩니다.

어떤 Node.js 코드가 수정되며, 그 출처는 어디인가요?

Node.js 줄 상류 현황 10월 수정값의 출처는 어디인가
26.x 현재, 2026년 10월 28일에 Active LTS로 전환되며, 2029년 4월 30일에 지원이 종료됩니다. Node.js 26.12.1
24.x 2026년 10월 20일부터 LTS 유지보수, 2028년 4월 30일 지원 종료 Node.js 24.22.1
22.x 2027년 4월 30일까지 LTS 유지보수 Node.js 22.23.4
20.x 2026년 4월 30일부터 서비스 종료 상류에서 수정된 사항 없음. 런타임용 ELS
18.x 2025년 4월 30일부터 서비스 종료 상류에서 수정된 사항 없음. 런타임용 ELS
16.x 및 14.x 2023년부터 단종됨 상류에서 수정된 사항 없음. 런타임용 ELS
12.x 2022년 4월 30일부터 서비스 종료됨 상류에서 수정된 사항 없음. 런타임용 ELS
홀수 행 (25, 23 및 그 이전) Lifecycle 종료 업스트림에서 수정된 사항이 없습니다. ELS는 Debian 12, Debian 13 및 Alpine에서 23을 지원합니다. 다른 버전은 요청 시 제공됩니다.

‘런타임용 ELS’ 문서에는 운영 체제별로 Node.js 12부터 26까지가 나열되어 있으며, 요청 시 다른 버전 및 아키텍처도 제공됩니다. 지원 종료(EOL) 이후에도 계속 실행하는 방법에 대해 자세히 알아보려면, EOL 이후 Node.js 확장 지원에 관한 이 가이드를 참조하십시오.

현재 문서에서 ‘활성 지원’ 항목에 다음과 같이 기재되어 있습니다:

운영 체제 패키지 유형 OS 버전 Node.js 버전
EL 6 (CentOS, CloudLinux, Oracle Linux 등) RPM 6.x 12, 14
EL 7 (CentOS, CloudLinux, Oracle Linux 등) RPM 7.x 12, 14, 16, 18, 20
EL 8 (AlmaLinux, CentOS, CentOS Stream, CloudLinux, Oracle Linux 등) RPM 8.x 12, 14, 16, 18, 20, 22, 24, 26
EL 9 (AlmaLinux, CentOS, CloudLinux, Oracle Linux 등) RPM 9.x 12, 14, 16, 18, 20, 22, 24, 26
EL 10 (AlmaLinux, CloudLinux, Oracle Linux 등) RPM 10.x 12, 14, 16, 18, 20, 22, 24, 26
Ubuntu DEB 18.04 12, 14, 16, 18, 20
Ubuntu DEB 20.04 12, 14, 16, 18, 20, 22
Ubuntu DEB 22.04 12, 14, 16, 18, 20, 22, 24
Ubuntu DEB 24.04 12, 14, 16, 18, 20, 22, 24, 26
Debian DEB 10 12, 14, 16, 18, 20
Debian DEB 11 12, 14, 16, 18, 20, 22
Debian DEB 12 12, 14, 16, 18, 20, 22, 23, 24
Debian DEB 13 12, 14, 16, 18, 20, 22, 23, 24, 26
Alpine Linux APK 3.23, 3.24 14, 16, 18, 23

빌드는 지원되는 모든 OS의 x86_64용과, Debian 12, Debian 13 및 Alpine 3.23 이상 버전의 aarch64(arm64)용으로 제공됩니다. 이번 주에는 Imperva의 코드 실행 시연이 arm64에서 실행되었기 때문에 arm64용 빌드가 특히 중요합니다.

배포 패키지의 작동 방식은 약간 다릅니다. 데비안(Debian) 및 우분투(Ubuntu) 패키지와 홈브루(Homebrew)를 포함한 일부 빌드는 Node.js에 번들로 포함된 Brotli 라이브러리 대신 공유 Brotli 라이브러리를 링크합니다. 이 경우, 패키지 관리자가 제공하는 Brotli 라이브러리의 보안 업데이트를 확인해야 합니다. 확인하는 데는 한 줄이면 충분합니다:

ldd "$(command -v node)" | grep -i brotli

출력에 ‘libbrotli’ 경로가 표시되면 해당 바이너리가 공유 Brotli 라이브러리를 링크하고 있음을 의미합니다. 일치하는 항목이 없다면 번들로 제공되거나 정적 링크된 사본임을 시사하며, 이는 nodejs.org의 공식 빌드가 배포되는 방식입니다. 하지만 이 명령어만으로는 이를 확인할 수 없으므로, 필요한 경우 패키지 정보나 빌드 구성을 확인해 보시기 바랍니다. ldd 리눅스에서만 작동합니다. Homebrew가 설치된 macOS에서는, otool -L "$(command -v node)" | grep -i brotli 같은 역할을 합니다.

지금 바로 Runtimes용 ELS를 확인해 보세요 →

패치하고, 재시작한 다음, 그 효과를 입증하라

먼저 목록을 확인해 보세요. 목록은 항상 예상보다 길기 때문입니다. nvm이나 Volta 같은 버전 관리 도구는 바이너리 파일을 홈 디렉터리에 저장하고, 배포판 패키지는 이를 /usr/bin, 그리고 ELS는 다음 경로에서 빌드됩니다. /opt/alt/ 버전별로 별도의 활성화 스크립트를 사용합니다. 이 두 개의 Bash 루프는 모든 node 현재 PATH에 포함되어 있다면, /opt/alt/, 각 항목이 보고하는 버전은 다음과 같습니다:

type -ap node | while read -r n; do echo "$n $("$n" -v)"; done
for e in /opt/alt/alt-nodejs*/enable; do [ -f "$e" ] && ( . "$e" && echo "$e $(node -v)" ); done

이를 통해 초기 인벤토리를 확인할 수 있지만, 이는 각 서비스가 실제로 실행하는 것과 동일하지는 않습니다. systemd 유닛, PM2 구성, CI 러너 및 컨테이너 베이스 이미지는 각각 서로 다른 바이너리를 가리킬 수 있으므로, 이 부분들도 함께 확인해야 합니다. RPM 기반 시스템에서는 ELS 빌드가 다음을 통해 업데이트됩니다. yum update 'alt-nodejs*', 그리고 DEB 및 APK에 대한 설명은 같은 문서 페이지에 있습니다.

업스트림 빌드에서 Brotli 수정 사항에 대한 버전 문자열을 믿지 마세요. Node.js는 Brotli의 버전을 올리지 않은 채 해당 패치를 선별적으로 적용했기 때문에, process.versions.brotli 업데이트 전후로 똑같이 보입니다. 이번 릴리스에서는 패치된 업스트림 바이너리에는 있지만 패치되지 않은 바이너리에는 없는 새로운 zlib 상수가 공개되었습니다:

node -p "'BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH' in require('zlib').constants"

true 이는 고정 디코더가 존재함을 의미합니다. 이 확인 방법은 공식 업스트림 빌드에서만 신뢰할 수 있으므로, 배포판이나 ELS 빌드의 경우 공급업체의 권고 사항을 따르십시오. 프로젝트 자체의 npx is-my-node-vulnerable 업스트림 설치에도 유용하지만, 버전 번호를 기준으로 작동하기 때문에 백포트된 빌드가 실제로는 취약하지 않더라도 취약해 보일 수 있습니다.

그런 다음 재시작해야 하는데, 이 단계가 생략되고 있습니다. 실행 중인 Node.js 프로세스는 종료될 때까지 기존 디코더를 유지하며, 컨테이너는 패치된 베이스에서 재구축된 이미지를 통해 재배포될 때까지 이를 유지합니다. SEA 및 시작 스냅샷은 패치된 런타임으로 재구축해야 하며, CVE-2026-106074의 경우 이 재구축이 바로 수정 조치입니다. 다음을 다시 실행하십시오. ps 이 게시물 상단에 있는 명령어를 실행하고, 업데이트가 적용된 후 시작된 모든 Node.js 프로세스를 확인하세요. 단일 실행 파일 형태의 애플리케이션이나 이름이 변경된 바이너리는 해당 목록에 표시되지 않으므로, 서비스 이름을 통해 직접 확인하시기 바랍니다.

마지막으로, 스캐너의 버전 비교 결과만으로 티켓을 종결하지 마십시오. 백포트된 빌드라도 여전히 원래의 업스트림 버전을 보고할 수 있습니다. 사용 중인 도구가 지원하는 경우, CSAF 권고 사항을 포함하는 TuxCare의 Node.js용 기계 판독 가능 보안 데이터를 도구에 입력하고, 설치된 패키지, 해당 패키지가 해결하는 권고 사항, 그리고 실제로 트래픽을 처리하는 프로세스에 대한 기록을 보관하십시오. 이것이 바로 감사관이 요청할 내용입니다.

런타임 결함이 왜 다른 영향을 미치는가

런타임 역시 의존성 중 하나이며, 일단 이에 대한 수정 패치가 더 이상 제공되지 않게 되면, 해당 런타임이 운영 환경에 남아 있는 한 모든 새로운 핵심 취약점은 해결되지 않은 채로 남게 됩니다. 2년 전 버전의 lodash는 절대 사용하지 않을 팀들이, 2025년부터 보안 패치 제공이 중단된 Node.js 버전을 아무렇지 않게 사용해 코드를 실행하고 있습니다.

이번 주에는 계획을 세울 시간이 얼마나 부족한지도 여실히 드러났습니다. 사전 경보가 발령된 지 7일 만에 취약점이 공개되었고, 다음 날에는 공개 개념 증명(PoC)이 나왔으며, 같은 날 기본 이미지에 대한 작동하는 익스플로잇이 등장했고, 패치는 정확히 세 번의 릴리스 버전에만 적용되었습니다. “다음 분기에 업그레이드하겠다”는 말은 다음 분기에는 아주 훌륭한 계획일 수 있습니다. 하지만 이번 주에는 전혀 계획이 아닙니다.

그러니 지금 지원되는 라인에 패치를 적용하고, 재시작이 필요한 서비스는 재시작하세요. 업스트림에서 남겨둔 Node.js 라인의 경우, 해당 라인에 대한 빌드가 적용되는 대로 수정된 ELS 빌드로 이전하고, 그동안 신뢰할 수 없는 Brotli 데이터에 대한 노출을 차단한 뒤, 마이그레이션 일정을 수립하세요.

지금 바로 Runtimes용 ELS를 확인해 보세요 →

이 사건들이 어떻게 전개되었는지

날짜 이벤트
2월 2026 Brotli 수정 커밋이 google/brotli에 반영되었으며, 보안 릴리스는 포함되지 않았습니다.
10월 14, 2026 Antoine du Hamel이 oss-security에 Node.js 사전 경보를 게시했으며, 심각도는 최고 수준인 ‘High’입니다.
10월 21, 2026 Node.js 22.23.4, 24.22.1 및 26.12.1 버전이 출시되어 10건의 CVE가 수정되었습니다.
10월 21, 2026 Brotli가 1.2.1, 1.1.1 및 1.0.10 버전을 출시했으며, Vercel은 인바운드 경로에 대한 WAF 규칙을 배포했습니다.
10월 22, 2026 공개 개념 증명(PoC)은 의도적으로 취약하게 만들어진 빌드에서만 코드 실행 단계에 도달합니다.
10월 22, 2026 Imperva, 공식 Node.js 24.22.0 이미지에서 코드 실행이 가능한 ‘Node2Shell’을 공개했습니다.
2026년 10월 22일부터 24일까지 지원 종료된 Node.js 제품군을 포함하는 Runtimes 빌드에 대한 ELS 예상 기간

출처

이 게시물의 출처로는 Node.js 2026년 10월 21일 보안 릴리스 권고문, 22.23.4 및 24.22.1 릴리스 노트, oss-security의 사전 경보, Node.js 릴리스 일정, google/brotli 수정 커밋, eMudhra 차단 목록 풀 리퀘스트, Vercel의 보안 공지를 들 수 있으며, Imperva의 Node2Shell 연구, The Hacker News의 관련 보도, CISA KEV 카탈로그, is-my-node-vulnerable, TuxCare의 Node.js용 ELS for Runtimes 문서 및 기계 판독 가능 보안 데이터 등이 있습니다.

4,500명 이상의 Linux 및 오픈 소스 전문가와 함께하세요!

한 달에 두 번. 스팸이 없습니다.

목차
필요한 오픈 소스 보안에 대한 답변 얻기

4,500명 이상의 Linux 및 오픈 소스 전문가와 함께하세요!

한 달에 두 번. 스팸이 없습니다.