๐ŸŒ ์•ˆ ๋‹ฌ๋ผ๊ณ  ํ–ˆ๋Š”๋ฐ๋„ ํ‘ผ๋‹ค: ์‘๋‹ต ์••์ถ•์ด ์‹ ๋ขฐ ๊ฒฝ๊ณ„์ธ ์ด์œ 

@leekh8 ยท November 10, 2026 ยท 10 min read

์ง€๋‚œ React 18 SSR NUL ๋ฐ”์ดํŠธ ๊ธ€ ๋์— ๋‹ค์Œ์€ ๋„คํŠธ์›Œํฌ ์ฐจ๋ก€๋ผ๊ณ  ์ ์—ˆ๋‹ค. ๊ทธ ์‚ฌ์ด์— ์†Œ์žฌ๊ฐ€ ์™”๋‹ค.

2026๋…„ 10์›” 21์ผ Node.js๊ฐ€ ๋ณด์•ˆ ๋ฆด๋ฆฌ์Šค๋ฅผ ๋ƒˆ๋‹คnode-oct2026. ์—ด ๊ฑด ์ค‘ ๊ฐ€์žฅ ๋†’์€ ๊ฒƒ์ด ๋ฒˆ๋“ค๋œ Brotlirfc7932 ๋””์ฝ”๋”์˜ ๊ฒฝ๊ณ„ ๋ฐ– ์“ฐ๊ธฐ์˜€๋‹ค. ๊ณต์ง€ ์ œ๋ชฉ์ด ์ด๋ ‡๋‹ค.

Node.js Brotli decoder out-of-bounds write permits remote code execution (CVE-2026-111497) - (high)node-oct2026

์ œ๋ชฉ๋งŒ ๋ณด๊ณ  ๋“  ์ฒซ ์ƒ๊ฐ์€ ์ด๊ฒƒ์ด์—ˆ๋‹ค.

์šฐ๋ฆฌ๋Š” brotli ์•ˆ ์“ฐ๋Š”๋ฐ.

์žฌ ๋ดค๋‹ค. ์ฒ˜์Œ ์ธก์ •์ด ํ‹€๋ ธ๊ณ , ํ‹€๋ฆฐ ๋ฐฉํ–ฅ์ด ํ•˜ํ•„ ์•ˆ์‹ฌํ•˜๋Š” ์ชฝ์ด์—ˆ๋‹ค.

1. ์ฒ˜์Œ ์ธก์ •: br์„ ๋‹ฌ๋ผ๊ณ  ํ•˜์ง€ ์•Š๋Š”๋‹ค

๋กœ์ปฌ์— ์„œ๋ฒ„๋ฅผ ๋„์›Œ ๋“ค์–ด์˜ค๋Š” Accept-Encoding์„ ๊ทธ๋Œ€๋กœ ์ฐ์—ˆ๋‹ค.

import http from "node:http";

const srv = http.createServer((req, res) => {
  console.log(req.url, req.headers["accept-encoding"]);
  res.end("ok");
});
srv.listen(0, "127.0.0.1");

Node 24.11.1์—์„œ ๋‚˜์˜จ ๊ฐ’์ด๋‹ค.

๋ณด๋‚ด๋Š” ์ชฝ Accept-Encoding
fetch(url) gzip, deflate
http.get(url) (ํ—ค๋” ์—†์Œ)

br์ด ์—†๋‹ค. ์—ฌ๊ธฐ์„œ ๋ฉˆ์ถ”๋ฉด "brotli ๋””์ฝ”๋”๋Š” ๋‚ด ์ฝ”๋“œ์—์„œ ์•ˆ ๋Œ์•„๊ฐ„๋‹ค"๊ฐ€ ๋œ๋‹ค. ์‹ค์ œ๋กœ ๊ทธ๋ ‡๊ฒŒ ์ ์–ด ๋’€๋‹ค๊ฐ€ ์ง€์› ๋‹ค.

2. ํ‹€๋ฆฐ ์ด์œ : ์„œ๋ฒ„๋ฅผ http๋กœ ๋„์› ๋‹ค

fetch์˜ ๊ธฐ๋ณธ Accept-Encoding์€ ์Šคํ‚ด์— ๋”ฐ๋ผ ๊ฐˆ๋ฆฐ๋‹ค. Node์— ๋ฒˆ๋“ค๋œ undici ์†Œ์Šค์— ๋ถ„๊ธฐ๊ฐ€ ๊ทธ๋Œ€๋กœ ์žˆ๋‹คundici-src.

if (!httpRequest.headersList.contains('accept-encoding', true)) {
  if (urlHasHttpsScheme(requestCurrentURL(httpRequest))) {
    httpRequest.headersList.append('accept-encoding', 'br, gzip, deflate, zstd', true)
  } else {
    httpRequest.headersList.append('accept-encoding', 'gzip, deflate', true)
  }
}

๋‚ด ํ…Œ์ŠคํŠธ ์„œ๋ฒ„๋Š” http://127.0.0.1 ์ด์—ˆ๋‹ค. ๊ทธ๋ž˜์„œ else ์ชฝ ๊ฐ’์„ ์žฌ๊ณ  ์žˆ์—ˆ๋‹ค. ์ž์ฒด ์„œ๋ช… ์ธ์ฆ์„œ๋กœ https ์„œ๋ฒ„๋ฅผ ํ•˜๋‚˜ ๋” ๋„์›Œ ๊ฐ™์€ ์ธก์ •์„ ๋‹ค์‹œ ํ–ˆ๋‹ค.

์š”์ฒญํ•œ ์Šคํ‚ด ์„œ๋ฒ„๊ฐ€ ๋ฐ›์€ Accept-Encoding
http://127.0.0.1:โ€ฆ gzip, deflate
https://localhost:โ€ฆ br, gzip, deflate

br์ด ๋งจ ์•ž์— ์žˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์‹ค์ œ ์•„์›ƒ๋ฐ”์šด๋“œ ์š”์ฒญ์€ ๊ฑฐ์˜ ์ „๋ถ€ https๋‹ค. ์ฆ‰ ๊ธฐ๋ณธ๊ฐ’ ๊ทธ๋Œ€๋กœ ์“ฐ๋Š” ์ฝ”๋“œ๊ฐ€ brotli๋ฅผ ๋จผ์ € ๋‹ฌ๋ผ๊ณ  ํ•˜๊ณ  ์žˆ์—ˆ๋‹ค.

โš ๏ธ ์ด ๋ถ„๊ธฐ๋Š” Node ๊ณต์‹ ๋ฌธ์„œ์— ์—†๋‹ค. doc/api ์ „์ฒด์—์„œ accept-encoding์ด ๋‚˜์˜ค๋Š” ํŒŒ์ผ์€ zlib.md์™€ http2.md ๋‘˜๋ฟ์ด๊ณ , fetch๋ฅผ ๋‹ค๋ฃจ๋Š” ๋ฌธ์„œ์—๋Š” ์—†๋‹ค. ๋ฒˆ๋“ค๋œ undici ์†Œ์Šค์—์„œ๋งŒ ํ™•์ธ๋œ๋‹ค.

๋กœ์ปฌ์—์„œ ์žฌ๋Š” ๊ฒƒ์€ ์ข‹์€ ์Šต๊ด€์ด์ง€๋งŒ, ์Šคํ‚ด์„ ๋ฐ”๊พธ๋ฉด ๊ฐ’์ด ๋ฐ”๋€Œ๋Š” ์ฝ”๋“œ๋ฅผ http๋กœ ์žฌ๋ฉด ๋ฐ˜๋Œ€ ๊ฒฐ๋ก ์ด ๋‚˜์˜จ๋‹ค. ๋‚ด๊ฐ€ ๊ฒช์€ ๊ฒƒ์ด ์ •ํ™•ํžˆ ๊ทธ๊ฒƒ์ด๋‹ค.

3. ๊ทธ๋ฆฌ๊ณ  ์•ˆ ๋‹ฌ๋ผ๊ณ  ํ•ด๋„ ํ‘ผ๋‹ค

๋” ์ค‘์š”ํ•œ ์ชฝ์ด ๋‚จ์•„ ์žˆ๋‹ค. HTTP์—์„œ Accept-Encoding์€ ์š”์ฒญ์ด๊ณ rfc9110-accept-encoding Content-Encoding์€ ํ†ต๋ณด๋‹คrfc9110-content-encoding. ์„œ๋ฒ„๊ฐ€ ๋‚ด๊ฐ€ ์ ์–ด ๋ณด๋‚ธ ๋ชฉ๋ก์„ ์ง€ํ‚ฌ ์˜๋ฌด๋Š” ๋ช…์„ธ์— ์—†๋‹ค.

๋ฌป์ง€ ์•Š๊ณ  ๋Š˜ brotli๋กœ ๋‹ตํ•˜๋Š” ์„œ๋ฒ„๋ฅผ ์„ธ์›Œ ๋„ค ๊ฐ€์ง€๋กœ ๋ˆŒ๋Ÿฌ ๋ดค๋‹ค.

// ์š”์ฒญ์— ๋ญ๊ฐ€ ์ ํ˜€ ์žˆ๋“  ๋Š˜ brotli ๋กœ ๋‹ตํ•œ๋‹ค
const body = zlib.brotliCompressSync(Buffer.from("ํ’€๋ ธ๋‹ค", "utf8"));
res.writeHead(200, { "content-encoding": "br" });
res.end(body);
์š”์ฒญ์— ์ ์€ ๊ฒƒ ๊ฒฐ๊ณผ
์•„๋ฌด๊ฒƒ๋„ ์•ˆ ์ ๋Š”๋‹ค (๊ธฐ๋ณธ) ํ’€์–ด์„œ ์ค€๋‹ค
gzip ๋งŒ ๋‹ฌ๋ผ๊ณ  ํ•œ๋‹ค ํ’€์–ด์„œ ์ค€๋‹ค
identity (์••์ถ•ํ•˜์ง€ ๋ง๋ผ) ํ’€์–ด์„œ ์ค€๋‹ค
gzip, br;q=0 (br์„ ๊ฑฐ์ ˆํ•œ๋‹ค) ํ’€์–ด์„œ ์ค€๋‹ค

๋„ค ๊ฒฝ์šฐ ์ „๋ถ€ await r.text()๊ฐ€ "ํ’€๋ ธ๋‹ค"๋ฅผ ๋Œ๋ ค์คฌ๋‹ค. ์••์ถ•์„ ์“ฐ์ง€ ๋ง๋ผ๊ณ  ๋ช…์‹œํ•ด๋„ ๋””์ฝ”๋”๊ฐ€ ๋Œ์•˜๋‹ค.

์ด๊ฒƒ์€ ๋ฒ„๊ทธ๊ฐ€ ์•„๋‹ˆ๋ผ ์„ค๊ณ„๋‹ค. ํด๋ผ์ด์–ธํŠธ๋Š” ๋ฐ›์€ ์‘๋‹ต์— ์ ํžŒ ๋Œ€๋กœ ํ‘ผ๋‹คundici. ์ ํžŒ ๋Œ€๋กœ ์•ˆ ํ’€๋ฉด ๋ณธ๋ฌธ์„ ์ฝ์„ ๋ฐฉ๋ฒ•์ด ์—†๋‹ค.

๊ทธ๋ž˜์„œ Accept-Encoding์€ ๋ฐฉ์–ด๊ฐ€ ์•„๋‹ˆ๋‹ค

  • Accept-Encoding์€ ๋‚ด๊ฐ€ ์›ํ•˜๋Š” ๊ฒƒ์„ ์ ๋Š” ์นธ์ด๋‹ค
  • ๋ฌด์—‡์ด ๋Œ์•„์˜ฌ์ง€๋Š” ์ƒ๋Œ€๊ฐ€ ๊ณ ๋ฅธ๋‹ค
  • ๋””์ฝ”๋”์— ๋“ค์–ด๊ฐ€๋Š” ๋ฐ”์ดํŠธ๋Š” ์ „๋ถ€ ์ƒ๋Œ€๊ฐ€ ๋งŒ๋“  ๊ฒƒ์ด๋‹ค

์••์ถ•์„ ์•ˆ ์“ฐ๊ธฐ๋กœ ์ •ํ–ˆ๋‹ค๊ณ  ์••์ถ• ํ•ด์ œ ์ฝ”๋“œ๊ฐ€ ์•ˆ ๋„๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋‹ค. ์••์ถ• ํ•ด์ œ๋Š” ์‘๋‹ต์„ ๋ฐ›๋Š” ์ชฝ์—์„œ ์ผ์–ด๋‚˜๊ณ , ๊ทธ ์ž…๋ ฅ์€ ์ฒ˜์Œ๋ถ€ํ„ฐ ๋๊นŒ์ง€ ์ƒ๋Œ€ ๊ฒƒ์ด๋‹ค. ๊ฑฐ๊ธฐ๊ฐ€ ์‹ ๋ขฐ ๊ฒฝ๊ณ„๋‹ค.

์ƒ๋Œ€
๋‚ด ํ”„๋กœ์„ธ์Šค
Accept-Encoding ์€ ๋‚ด๊ฐ€ ์ ๋Š”๋‹ค
ํ‘ผ ๋ณธ๋ฌธ
Content-Encoding br ๊ณผ ๋ฐ”์ดํŠธ
์„œ๋ฒ„
HTTP ํด๋ผ์ด์–ธํŠธ
๋‚ด ์ฝ”๋“œ
์••์ถ• ํ•ด์ œ๊ธฐ

์ฃผํ™ฉ์ƒ‰ ์นธ์˜ ์ž…๋ ฅ์€ ๋‚ด ํ”„๋กœ์„ธ์Šค ์•ˆ์— ์žˆ์ง€๋งŒ ๋‚ด๊ฐ€ ๋งŒ๋“  ๊ฒƒ์ด ์•„๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ์š”์ฒญ์— ๋ฌด์—‡์„ ์ ์—ˆ๋Š”์ง€๋Š” ๊ทธ ์นธ์— ๋“ค์–ด์˜ค๋Š” ๋ฐ”์ดํŠธ๋ฅผ ๋ฐ”๊พธ์ง€ ๋ชปํ•œ๋‹ค.

4. ๋ฌด์—‡์ด ์–ด๋–ป๊ฒŒ ๊นจ์กŒ๋‚˜

Node ๊ณต์ง€๊ฐ€ ์ ์€ ์›์ธ์ด ์งง๊ณ  ๋ถ„๋ช…ํ•˜๋‹ค.

An invalid block switch was reported as a temporary need for more input instead of a permanent format error, so the streaming decoder kept appending input bytes to an eight-byte internal buffer.node-oct2026

์ž˜๋ชป๋œ ๋ธ”๋ก ์ „ํ™˜์„ ์˜๊ตฌ ํ˜•์‹ ์˜ค๋ฅ˜๋กœ ๋ณด๊ณ ํ•ด์•ผ ํ•˜๋Š”๋ฐ ์ž…๋ ฅ์ด ๋” ํ•„์š”ํ•˜๋‹ค๋กœ ๋ณด๊ณ ํ–ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ŠคํŠธ๋ฆฌ๋ฐ ๋””์ฝ”๋”๊ฐ€ 8๋ฐ”์ดํŠธ ๋‚ด๋ถ€ ๋ฒ„ํผ์— ์ž…๋ ฅ์„ ๊ณ„์† ์ด์–ด ๋ถ™์˜€๋‹ค. ์ง€์ •๋œ ๋ถ„๋ฅ˜๊ฐ€ ๋‘˜์ธ ๊ฒƒ๋„ ์ด๊ฒƒ๊ณผ ๋งž๋ฌผ๋ฆฐ๋‹ค. ๊ฒฝ๊ณ„ ๋ฐ– ์“ฐ๊ธฐ(CWE-787)์™€ ๋ฐ˜ํ™˜๊ฐ’ ํ™•์ธ ๋ˆ„๋ฝ(CWE-252)์ด๋‹คcve-record.

Brotli ์ชฝ ์ˆ˜์ • ์ปค๋ฐ‹ ์ œ๋ชฉ์ด "Detect and report invalid stream earlier"๋‹คbrotli-commit. ์—ฌ๋Ÿฌ ํ•จ์ˆ˜์˜ ๋ฐ˜ํ™˜ํ˜•์ด ์ฐธ๊ฑฐ์ง“์—์„œ ์˜ค๋ฅ˜ ์ฝ”๋“œ๋กœ ๋ฐ”๋€Œ์—ˆ๋‹ค. ์ฐธ๊ฑฐ์ง“์œผ๋กœ๋Š” "์‹คํŒจ"์™€ "์•„์ง ๋ชจ์ž๋žŒ"์„ ๊ตฌ๋ณ„ํ•  ์ˆ˜ ์—†์—ˆ๋‹ค๋Š” ๋œป์ด๋‹ค.

์‹ฌ๊ฐ๋„๊ฐ€ ๊ธฐ๊ด€๋งˆ๋‹ค ๋‹ค๋ฅด๋‹ค

๊ธฐ๊ด€ ๋“ฑ๊ธ‰
Node.js high (CVSS ๋ฒกํ„ฐ, ์ ์ˆ˜๋ฅผ ๊ณต์ง€์— ์ ์ง€ ์•Š์•˜๋‹ค)node-oct2026
CVE ๋ ˆ์ฝ”๋“œ (Google) CVSS 4.0 9.2 Criticalcve-record
NVD CVSS 3.1 9.8 Criticalnvd

์„ธ ์ˆซ์ž๊ฐ€ ๋‹ค ์›๋ฌธ์ด๋‹ค. ํ•œ์ชฝ๋งŒ ์ธ์šฉํ•˜๋ฉด ๊ธ€์ด ํ‹€๋ฆฌ์ง€๋Š” ์•Š์•„๋„ ์ข์•„์ง„๋‹ค.

5. ์•„์›ƒ๋ฐ”์šด๋“œ ์š”์ฒญ์ด ์žˆ์œผ๋ฉด ์ด๋ฏธ ๋ฌผ๋ ค๋ฐ›์•˜๋‹ค

์ด ๋””์ฝ”๋”๋Š” ๋Ÿฐํƒ€์ž„์— ๋ฒˆ๋“ค๋˜์–ด ์žˆ๋‹ค(deps/brotli)node-deps. ๋‚ด๊ฐ€ ์„ค์น˜ํ•˜์ง€ ์•Š์•˜๊ณ  package.json์—๋„ ์—†๊ณ  ์˜์กด์„ฑ ๋ชฉ๋ก์„ ๋’ค์ ธ๋„ ์•ˆ ๋‚˜์˜จ๋‹ค.

๋‹ฟ๋Š” ์ฝ”๋“œ๋Š” ๋„“๋‹ค.

ํ”ํ•œ ์ฝ”๋“œ ์™œ ๋‹ฟ๋‚˜
๋งํฌ ๋ฏธ๋ฆฌ๋ณด๊ธฐ, ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์ˆ˜์ง‘ ์‚ฌ์šฉ์ž๊ฐ€ ๋„ฃ์€ URL์„ ๊ฐ€์ ธ์™€ ๋ณธ๋ฌธ์„ ์ฝ๋Š”๋‹ค
์›นํ›… ๊ฒ€์ฆ, ์ฝœ๋ฐฑ ํ™•์ธ ์ƒ๋Œ€ ์„œ๋ฒ„์˜ ์‘๋‹ต์„ ์ฝ๋Š”๋‹ค
ํฌ๋กค๋Ÿฌ, ์‚ฌ์ดํŠธ๋งต ์ƒ์„ฑ๊ธฐ ์ž„์˜ ์ฃผ์†Œ๋ฅผ ์—ด์–ด ๋ณธ๋ฌธ์„ ํ›‘๋Š”๋‹ค
์™ธ๋ถ€ API ์—ฐ๋™ ๊ทธ API๊ฐ€ ๋šซ๋ฆฌ๊ฑฐ๋‚˜ ์ค‘๊ฐ„์ด ๋ผ๋ฉด ์‘๋‹ต์ด ๋ฐ”๋€๋‹ค
์ด๋ฏธ์ง€, ํŒŒ์ผ ๋‚ด๋ ค๋ฐ›๊ธฐ ๊ฐ™์€ ๊ธธ์„ ์“ด๋‹ค

๋งˆ์ง€๋ง‰ ์ค„์ด ์ค‘์š”ํ•˜๋‹ค. ์ƒ๋Œ€๊ฐ€ ๋‚ด ์ ์ด ์•„๋‹ˆ์–ด๋„ ๋œ๋‹ค. ์ƒ๋Œ€๊ฐ€ ๋‹นํ•˜๋ฉด ๋‚ด ๋””์ฝ”๋”์— ๊ทธ ๋ฐ”์ดํŠธ๊ฐ€ ๋“ค์–ด์˜จ๋‹ค.

node:zlib์˜ ๊ณต๊ฐœ API๋กœ๋„ ๋ฐ”๋กœ ๋‹ฟ๋Š”๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ณต์‹ zlib ๋ฌธ์„œ๊ฐ€ ๊ถŒํ•˜๋Š” HTTP ํด๋ผ์ด์–ธํŠธ ์˜ˆ์‹œ๊ฐ€ Accept-Encoding: br,gzip,deflate,zstd๋กœ ์š”์ฒญํ•ด์„œ case 'br'์—์„œ createBrotliDecompress()๋กœ ๋ฐ›๋Š” ๋ชจ์–‘์ด๋‹คnode-zlib. ๋ฌธ์„œ๊ฐ€ ๊ฐ€๋ฅด์น˜๋Š” ํŒจํ„ด์ด ๊ทธ๋Œ€๋กœ ๊ทธ ๊ฒฝ๋กœ๋‹ค.

SSRF ๊ฐ€๋“œ๊ฐ€ ์ด๊ฒƒ์„ ๋ง‰์•„ ์ฃผ์ง€ ์•Š๋Š”๋‹ค

SSRF ๊ฐ€๋“œ ์‘๋‹ต ๋””์ฝ”๋”ฉ
์žฌ๋Š” ๊ฒƒ ์–ด๋””๋กœ ๊ฐ€๋‚˜ (ํ˜ธ์ŠคํŠธ, IP ๋Œ€์—ญ) ๋ฌด์—‡์ด ๋Œ์•„์˜ค๋‚˜ (๋ณธ๋ฌธ ๋ฐ”์ดํŠธ)
๋ง‰๋Š” ๊ฒƒ ๋‚ด๋ถ€๋ง, ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ๋์ owasp-ssrf (์•„๋ฌด๊ฒƒ๋„)

๊ณต๊ฐœ ์ธํ„ฐ๋„ท ์ฃผ์†Œ๋กœ๋งŒ ๋‚˜๊ฐ€๋„๋ก ์™„๋ฒฝํžˆ ๋ง‰์•„๋„, ๊ทธ ๊ณต๊ฐœ ์ฃผ์†Œ๊ฐ€ ๋Œ๋ ค์ฃผ๋Š” ๋ฐ”์ดํŠธ๋Š” ๊ทธ๋Œ€๋กœ ๋””์ฝ”๋”์— ๋“ค์–ด๊ฐ„๋‹ค. ๋‘ ๊ฒ€์‚ฌ๋Š” ๋‹ค๋ฅธ ์ถ•์ด๋ผ ํ•˜๋‚˜๊ฐ€ ๋‹ค๋ฅธ ํ•˜๋‚˜๋ฅผ ๋Œ€์‹ ํ•˜์ง€ ๋ชปํ•œ๋‹ค.

๋ง๋ถ™์—ฌ, ๋งŽ์€ SSRF ๊ฐ€๋“œ๊ฐ€ ์‹œ์ž‘ ์ฃผ์†Œ๋งŒ ๋ณด๊ณ  ๊ทธ ๋’ค ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ์™€ ์—ฐ๊ฒฐ ์‹œ์ ์˜ DNS ์žฌํ•ด์„์„ ๋‹ค์‹œ ์•ˆ ๋ณธ๋‹ค. ๊ฐ€๋“œ๋ฅผ ์“ฐ๊ณ  ์žˆ๋‹ค๋ฉด ์ด๊ฒƒ๋„ ๊ฐ™์ด ๋ณด๋Š” ํŽธ์ด ์ข‹๋‹ค.

6. ๊ณ ์น˜๋Š” ๊ธธ์€ ๋Ÿฐํƒ€์ž„ ํŒ๋ฟ์ด๋‹ค

์ค„ ๊ณ ์ณ์ง„ ํŒnode-oct2026
26.x 26.12.1
24.x 24.22.1
22.x 22.23.4

๐Ÿ›‘ ๋ฒˆ๋“ค๋œ brotli ํŒ ๋ฒˆํ˜ธ๋กœ ํŒ์ •ํ•˜๋ฉด ํ‹€๋ฆฐ๋‹ค. Node๋Š” brotli ๋ฒ„์ „์„ ์˜ฌ๋ฆฌ์ง€ ์•Š๊ณ  ํŒจ์น˜๋งŒ ์—ญ์ด์‹ํ–ˆ๋‹ค. ์ทจ์•ฝํ•œ v26.12.0๊ณผ ๊ณ ์ณ์ง„ v26.12.1์˜ deps/brotli/c/common/version.h๊ฐ€ ๋‘˜ ๋‹ค 1.2.0์ด๋‹คnode-deps. Brotli ๊ณต์‹ ์ˆ˜์ •ํŒ์€ 1.0.10 / 1.1.1 / 1.2.1์ธ๋ฐbrotli-releases Node๋Š” ๊ทธ ๋ฒˆํ˜ธ๋กœ ๊ฐ€์ง€ ์•Š๋Š”๋‹ค. ํŒ์ • ๊ธฐ์ค€์€ Node ํŒ ๋ฒˆํ˜ธ๋ฟ์ด๋‹ค.

ํŒ์„ ํ™•์ธํ•œ๋‹ค.

node --version                 # ๋‚ด ๋กœ์ปฌ

๋กœ์ปฌ ํŒ๊ณผ ์‹ค์ œ๋กœ ๋„๋Š” ํŒ์€ ๋‹ค๋ฅด๋‹ค. ์„ ์–ธํ•œ ์ž๋ฆฌ๋ฅผ ๋”ฐ๋กœ ๋ด์•ผ ํ•œ๋‹ค.

grep -rn "FROM node:" --include=Dockerfile .
grep -rn "node-version" .github/workflows/
grep -rn "NODE_VERSION" render.yaml vercel.json 2>/dev/null
cat .nvmrc .node-version 2>/dev/null
grep -rn '"node"' package.json        # engines.node

์ด ๋ช…๋ น๋“ค์„ ๋‚ด ํ”„๋กœ์ ํŠธ์— ๋Œ๋ ค ๋ณด๊ณ  ์•Œ๊ฒŒ ๋œ ๊ฒƒ์€, ํŒ์ด ์ ํ˜€ ์žˆ์ง€ ์•Š์€ ์ž๋ฆฌ๊ฐ€ ๊ฐ€์žฅ ๋งŽ๋‹ค๋Š” ๊ฒƒ์ด์—ˆ๋‹ค. engines.node๋„ .nvmrc๋„ ์—†์œผ๋ฉด ๋นŒ๋“œํ•˜๋Š” ์ชฝ์ด ์ž๊ธฐ ๊ธฐ๋ณธ๊ฐ’์„ ์“ด๋‹ค. ๊ทธ๋Ÿฌ๋ฉด "์–ด๋А ํŒ์œผ๋กœ ๋„๋Š”๊ฐ€"์— ๋‹ตํ•  ๋ฐฉ๋ฒ•์ด ์—†๊ณ , ๋‹ตํ•  ์ˆ˜ ์—†๋Š” ๊ฒƒ์€ ์˜ฌ๋ ธ๋Š”์ง€๋„ ํ™•์ธํ•  ์ˆ˜ ์—†๋‹ค.

์ง€์›์ด ๋๋‚œ ์ค„์€ ๊ณ ์นจ์ด ์•ˆ ์˜จ๋‹ค

์ค„ ์ง€์› ์ข…๋ฃŒnode-schedule
20.x Iron 2026-04-30
23.x 2025-06-01
25.x 2026-06-01

Node ๊ณต์ง€๊ฐ€ ํ•œ ๋ฌธ์žฅ์œผ๋กœ ์ ์–ด ๋‘”๋‹ค.

It's important to note that End-of-Life versions are always affected when a security release occurs.node-oct2026

โš ๏ธ ์ง€์›์ด ๋๋‚œ ์ค„์€ ใ€Œ์•„์ง ์•ˆ ์˜ฌ๋ ธ๋‹คใ€๊ฐ€ ์•„๋‹ˆ๋ผ ใ€Œ์•ž์œผ๋กœ๋„ ์•ˆ ๊ณ ์ณ์ง„๋‹คใ€๋‹ค. ํŒ์„ ์˜ฌ๋ฆฌ๋Š” ๊ฒƒ๊ณผ ์ค„์„ ๋ฐ”๊พธ๋Š” ๊ฒƒ์€ ๋‹ค๋ฅธ ์ผ์ด๋ผ ๋”ฐ๋กœ ์ ์–ด ๋‘๋Š” ํŽธ์ด ๋‚ซ๋‹ค.

์—ฌ๊ธฐ์„œ ํ•จ์ • ํ•˜๋‚˜. ๊ณต์‹ "Previous Releases" ํ‘œ์˜ ๋งˆ์ง€๋ง‰ ์นธ์€ "Last updated"์ด๊ณ  ์ง€์› ์ข…๋ฃŒ ๋‚ ์งœ๊ฐ€ ์•„๋‹ˆ๋‹ค. ๊ทธ ํ‘œ๋งŒ ๋ณด๋ฉด ํ˜„์—ญ LTS๊ฐ€ ๊ณง ๋๋‚˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ์ฝํžŒ๋‹ค. ์ข…๋ฃŒ ๋‚ ์งœ๋Š” ๋ฆด๋ฆฌ์Šค ์ผ์ • ํŒŒ์ผ์„ ๋ด์•ผ ํ•œ๋‹คnode-schedule.

7. ์•…์šฉ ์—ฌ๋ถ€๋Š” ์ถœ์ฒ˜์— ๋”ฐ๋ผ ๋ง์ด ๋‹ค๋ฅด๋‹ค

์ถœ์ฒ˜ ๋ฌด์—‡์„ ๋งํ–ˆ๋‚˜
Node.js ์•„๋ฌด ๋ง ์•ˆ ํ–ˆ๋‹ค. 10-21 ๊ณต์ง€์— ์•…์šฉ, PoC ์–ธ๊ธ‰์ด ์—†๋‹คnode-oct2026
CISA 2026-10-27 ์•…์šฉ๋œ ์ทจ์•ฝ์  ๋ชฉ๋ก์— ์˜ฌ๋ ธ๋‹ค. ์—ฐ๋ฐฉ๊ธฐ๊ด€ ๊ธฐํ•œ 2026-11-10cisa-kev

CISA๊ฐ€ ๊ทธ ๋ชฉ๋ก์— ์˜ฌ๋ฆฌ๋Š” ๊ธฐ์ค€ ์ž์ฒด๊ฐ€ ์•…์šฉ ์ฆ๊ฑฐ๋‹ค. ๊ทธ๋Ÿฌ๋‹ˆ ๋‘˜์„ ๊ฐ™์ด ์ ๋Š” ํŽธ์ด ์ •ํ™•ํ•˜๋‹ค. ๋ฒค๋” ๋ธ”๋กœ๊ทธ์—๋Š” ์‹ค์ œ๋กœ ์…ธ์„ ์–ป์—ˆ๋‹ค๋Š” ์ฃผ์žฅ์ด ์žˆ๊ณ , ๋ฐ˜๋Œ€๋กœ ๊ตฌ์กฐ์ƒ ์ฝ”๋“œ ์‹คํ–‰๊นŒ์ง€๋Š” ๋„๋‹ฌํ•˜์ง€ ๋ชปํ•œ๋‹ค๋Š” ๋ถ„์„๋„ ์žˆ๋‹ค. ๋‘˜์ด ์ถฉ๋Œํ•˜๋ฏ€๋กœ ์—ฌ๊ธฐ์„œ๋Š” ๋‹จ์ •ํ•˜์ง€ ์•Š๋Š”๋‹ค. Node ์ž์‹ ์˜ ํ‘œํ˜„์€ "can lead to a crash, disclosure of process memory, or remote code execution"์ด๋‹คnode-oct2026.

๊ทธ๋ฆฌ๊ณ  11์›” 11์ผ์— ๋‹ค์Œ ๋ณด์•ˆ ๋ฆด๋ฆฌ์Šค๊ฐ€ ์˜ˆ๊ณ ๋ผ ์žˆ๋‹ค. ์‚ฌ์ „ ๊ณต์ง€์— CVE ๋ชฉ๋ก์€ ์•„์ง ๋น„์–ด ์žˆ๊ณ  ์ตœ๊ณ  ์‹ฌ๊ฐ๋„๊ฐ€ HIGH๋ผ๊ณ ๋งŒ ์ ํ˜€ ์žˆ๋‹คnode-nov2026.

8. ๊ฐ™์ด ๋‚˜์˜จ ๊ฒƒ๋“ค์ด ๊ฐ™์€ ์ถ•์ด๋‹ค

๊ทธ ๋ฆด๋ฆฌ์Šค์˜ ๋‹ค๋ฅธ ๊ณ ์นจ๋“ค์„ ๋ฌถ์–ด ๋ณด๋ฉด ์ „๋ถ€ ๋“ค์–ด์˜ค๋Š” ๊ฒƒ์„ ํ•ด์„ํ•˜๋Š” ์ž๋ฆฌ๋‹ค.

์ž๋ฆฌ ํ•ด์„ํ•˜๋Š” ๊ฒƒ ์ž…๋ ฅ์„ ๊ณ ๋ฅด๋Š” ์ชฝ
์••์ถ• ํ•ด์ œ ์‘๋‹ต ๋ณธ๋ฌธ ์ƒ๋Œ€ ์„œ๋ฒ„
DNS ์ด๋ฆ„ ์ฒ˜๋ฆฌ (NUL ๊ธ€์ž๋กœ ์ž˜๋ฆผ) ์ด๋ฆ„ ์‘๋‹ต DNS ์‘๋‹ต์ž
TLS ํ˜ธ์ŠคํŠธ์ด๋ฆ„ ํ™•์ธ (์„ธ ๊ฑด) ์ธ์ฆ์„œ์˜ ์ด๋ฆ„ ์ธ์ฆ์„œ ์ œ์‹œ์ž

TLS ํ˜ธ์ŠคํŠธ์ด๋ฆ„ ์ชฝ์€ ์ „๊ฐ ์ˆซ์ž๋กœ ์“ด IP, ๋А์Šจํ•˜๊ฒŒ IP๋กœ ํ•ด์„๋˜๋Š” ํ˜ธ์ŠคํŠธ, ๋น„์ •๊ทœ IPv4 ํ˜ธ์ŠคํŠธ์ด๋ฆ„๊นŒ์ง€ ์„ธ ๊ฑด์ด๋‹คnode-oct2026. ๊ฐ™์€ ์ฃผ์— PHP ์ชฝ์—๋„ ์›๊ฒฉ ์ฝ”๋“œ ์‹คํ–‰์ด ์žˆ์—ˆ๊ณ  ๊ฑฐ๊ธฐ๋„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ฝ”๋“œ๊ฐ€ ์•„๋‹ˆ๋ผ ๋Ÿฐํƒ€์ž„์ด ํ’ˆ์€ ์ฒ˜๋ฆฌ๊ธฐ ์ชฝ์ด์—ˆ๋‹ค.

์ฝํžˆ๋Š” ๊ตํ›ˆ์€ ํ•˜๋‚˜๋‹ค. ๊ณต๊ฒฉ๋ฉด์„ ์…€ ๋•Œ ๋‚ด๊ฐ€ importํ•œ ๊ฒƒ๋งŒ ์„ธ๋ฉด ๋Ÿฐํƒ€์ž„์ด ๋Œ€์‹  ๋“ค๊ณ  ์žˆ๋Š” ํŒŒ์„œ์™€ ๋””์ฝ”๋”๊ฐ€ ํ†ต์งธ๋กœ ๋น ์ง„๋‹ค. ๊ทธ๊ฒƒ๋“ค์€ ์˜์กด์„ฑ ๋ชฉ๋ก์— ์—†๊ณ , ๋‚ด๊ฐ€ ์“ฐ๊ธฐ๋กœ ์ •ํ•œ ์ ๋„ ์—†๊ณ , ๋„๋Š” ์Šค์œ„์น˜๋„ ์—†๋‹ค.

9. ์‹ค๋ฌด ์ฒดํฌ๋ฆฌ์ŠคํŠธ

  • ๋„๋Š” ํŒ์„ ์•ˆ๋‹ค. ๋กœ์ปฌ(node --version)๊ณผ ๋นŒ๋“œ, ๋ฐฐํฌ ์ชฝ์„ ๋”ฐ๋กœ ํ™•์ธํ•œ๋‹ค. ๋‘˜์€ ๊ฑฐ์˜ ๋Š˜ ๋‹ค๋ฅด๋‹ค
  • ํŒ์„ ์„ ์–ธํ•ด ๋‘”๋‹ค. engines.node ๋˜๋Š” .nvmrc. ์—†์œผ๋ฉด ๋นŒ๋“œํ•˜๋Š” ์ชฝ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ๋Œ๊ณ , ๊ทธ๋Ÿฌ๋ฉด ์˜ฌ๋ ธ๋Š”์ง€ ํ™•์ธํ•  ๋ฐฉ๋ฒ•์ด ์—†๋‹ค
  • ๋ฒˆ๋“ค๋œ ์˜์กด์„ฑ ํŒ ๋ฒˆํ˜ธ๋กœ ํŒ์ •ํ•˜์ง€ ์•Š๋Š”๋‹ค. ๋Ÿฐํƒ€์ž„์ด ๋ฒˆํ˜ธ๋ฅผ ์˜ฌ๋ฆฌ์ง€ ์•Š๊ณ  ํŒจ์น˜๋งŒ ๋„ฃ๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋‹ค. ๊ธฐ์ค€์€ ๋Ÿฐํƒ€์ž„ ํŒ ๋ฒˆํ˜ธ๋‹ค
  • ์ง€์›์ด ๋๋‚œ ์ค„์„ ์“ฐ๊ณ  ์žˆ๋Š”์ง€ ์„ผ๋‹ค. ๋๋‚œ ์ค„์€ ๊ณ ์นจ์ด ์•ˆ ์˜จ๋‹ค. "์˜ฌ๋ฆด ๊ฒƒ"์ด ์•„๋‹ˆ๋ผ "์ค„์„ ๋ฐ”๊ฟ€ ๊ฒƒ"์œผ๋กœ ์ ๋Š”๋‹ค
  • ์•„์›ƒ๋ฐ”์šด๋“œ ์š”์ฒญ์ด ์žˆ๋Š” ์ž๋ฆฌ๋ฅผ ์ ์–ด ๋‘”๋‹ค. ๋งํฌ ๋ฏธ๋ฆฌ๋ณด๊ธฐ, ์›นํ›… ๊ฒ€์ฆ, ํฌ๋กค๋Ÿฌ, ํŒŒ์ผ ๋‚ด๋ ค๋ฐ›๊ธฐ, ์™ธ๋ถ€ API. ์ „๋ถ€ ์ƒ๋Œ€๊ฐ€ ๋งŒ๋“  ๋ฐ”์ดํŠธ๋ฅผ ํ•ด์„ํ•œ๋‹ค
  • SSRF ๊ฐ€๋“œ๋ฅผ "๋ฌด์—‡์ด ๋Œ์•„์˜ค๋‚˜"์˜ ๋ฐฉ์–ด๋กœ ์„ธ์ง€ ์•Š๋Š”๋‹ค. ๋‹ค๋ฅธ ์ถ•์ด๋‹ค. ๊ฐ€๋“œ๊ฐ€ ์žˆ์–ด๋„ ๋””์ฝ”๋”๋Š” ๊ทธ๋Œ€๋กœ ๋ˆ๋‹ค
  • ๋กœ์ปฌ์—์„œ ์žด ๋•Œ ์Šคํ‚ด์„ ๋งž์ถ˜๋‹ค. ๊ธฐ๋ณธ๊ฐ’์ด http์™€ https์—์„œ ๊ฐˆ๋ฆฌ๋Š” ์ฝ”๋“œ๊ฐ€ ์žˆ๋‹ค. ์‹ค์ œ๋กœ ์“ฐ๋Š” ์Šคํ‚ด์œผ๋กœ ์žฌ์•ผ ํ•œ๋‹ค

ํ•œ ์ค„๋กœ

Accept-Encoding์€ ๋‚ด๊ฐ€ ์›ํ•˜๋Š” ๊ฒƒ์„ ์ ๋Š” ์นธ์ด๊ณ , ๋ฌด์—‡์ด ๋Œ์•„์˜ฌ์ง€๋Š” ์ƒ๋Œ€๊ฐ€ ๊ณ ๋ฅธ๋‹ค. ๊ทธ ์‚ฌ์ด์— ์••์ถ• ํ•ด์ œ๊ธฐ๊ฐ€ ์žˆ๋‹ค.

๋‹ค์Œ ๊ธ€์—์„œ๋Š”

๋‹ค์Œ ๋ณด์•ˆ ์ฐจ๋ก€์—๋Š” HTTP ๋ณด์•ˆ ํ—ค๋” ๊ธ€์—์„œ ์˜ˆ๊ณ ํ•œ CSP Report-Only ํŽธ์„ ์“ด๋‹ค. ๋ณด๊ณ ๋งŒ ๋ฐ›๊ณ  ๋ง‰์ง€ ์•Š๋Š” ๋ชจ๋“œ๋กœ ์ •์ฑ…์„ ์žฌ๋Š” ๋ฐฉ๋ฒ•๊ณผ, ๊ทธ ๋ณด๊ณ ์„œ๊ฐ€ ์‹ค์ œ๋กœ ๋ฌด์—‡์„ ์•Œ๋ ค ์ฃผ๋Š”์ง€ ๋‹ค๋ฃฌ๋‹ค.

์ฐธ๊ณ ๋ฌธํ—Œ


๊ด€๋ จ ๊ธ€


  1. Node.js. "Wednesday, October 21, 2026 Security Releases" (CVE 10๊ฑด์˜ ์ œ๋ชฉ๊ณผ ์‹ฌ๊ฐ๋„, ์˜ํ–ฅ ๋ผ์ธ, ๊ณ ์ณ์ง„ ํŒ, End-of-Life ํŒ ๊ด€๋ จ ๋ฌธ์žฅ). https://nodejs.org/en/blog/vulnerability/october-2026-security-releasesโ†ฉ
  2. IETF. "RFC 7932 - Brotli Compressed Data Format". https://www.rfc-editor.org/rfc/rfc7932โ†ฉ
  3. nodejs/node. deps/undici/src/lib/web/fetch/index.js (์Šคํ‚ด์— ๋”ฐ๋ผ ๊ธฐ๋ณธ accept-encoding ์„ ๊ฐ€๋ฅด๋Š” ๋ถ„๊ธฐ). https://github.com/nodejs/node/blob/v26.12.1/deps/undici/src/lib/web/fetch/index.jsโ†ฉ
  4. IETF. "RFC 9110 - HTTP Semantics, 12.5.3. Accept-Encoding" (์š”์ฒญ์— ์ ๋Š” ์„ ํ˜ธ). https://www.rfc-editor.org/rfc/rfc9110#field.accept-encodingโ†ฉ
  5. IETF. "RFC 9110 - HTTP Semantics, 8.4. Content-Encoding" (ํ‘œํ˜„์— ์ ์šฉ๋œ ์ธ์ฝ”๋”ฉ์„ ์•Œ๋ฆฌ๋Š” ํ•„๋“œ). https://www.rfc-editor.org/rfc/rfc9110#field.content-encodingโ†ฉ
  6. nodejs/undici. Node.js์˜ fetch ๊ตฌํ˜„. ์‘๋‹ต์˜ Content-Encoding ์— ๋”ฐ๋ผ ๋ณธ๋ฌธ์„ ํ‘ผ๋‹ค. https://github.com/nodejs/undiciโ†ฉ
  7. CVE Program. "CVE-2026-111497 - Out-of-Bounds Write in Google Brotli Decoder" (CNA Google, CVSS 4.0 9.2, CWE-787 + CWE-252). https://www.cve.org/CVERecord?id=CVE-2026-111497โ†ฉ
  8. google/brotli. "Detect and report invalid stream earlier." (c/dec/decode.c ์ˆ˜์ • ์ปค๋ฐ‹). https://github.com/google/brotli/commit/0ed4268a4401abcb4472096340477cf4af7d1a2bโ†ฉ
  9. NVD. "CVE-2026-111497 Detail" (CVSS 3.1 9.8 Critical). https://nvd.nist.gov/vuln/detail/CVE-2026-111497โ†ฉ
  10. nodejs/node. deps/brotli (๋ฒˆ๋“ค๋œ Brotli ์†Œ์Šค. ์ˆ˜์ • ํŒ๊ณผ ์ทจ์•ฝ ํŒ์˜ c/common/version.h ๊ฐ€ ๊ฐ™๋‹ค). https://github.com/nodejs/node/tree/v26.12.1/deps/brotliโ†ฉ
  11. Node.js. "zlib - Compression and decompression" (brotliDecompress, createBrotliDecompress, ๊ทธ๋ฆฌ๊ณ  Accept-Encoding ์„ ๋ณด๋‚ด๊ณ  case 'br' ๋กœ ๋ฐ›๋Š” HTTP ํด๋ผ์ด์–ธํŠธ ์˜ˆ์‹œ). https://nodejs.org/docs/latest-v26.x/api/zlib.htmlโ†ฉ
  12. OWASP. "Server Side Request Forgery Prevention Cheat Sheet" (๋ชฉ์ ์ง€ ๊ฒ€์ฆ ์ค‘์‹ฌ์˜ ๋ฐฉ์–ด). https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.htmlโ†ฉ
  13. google/brotli. Releases v1.0.10 / v1.1.1 / v1.2.1 (๋ฆด๋ฆฌ์Šค ๋…ธํŠธ SECURITY ํ•ญ๋ชฉ). https://github.com/google/brotli/releases/tag/v1.2.1โ†ฉ
  14. nodejs/Release. schedule.json (๊ฐ ๋ฆด๋ฆฌ์Šค ์ค„์˜ start, maintenance, end ๋‚ ์งœ). https://raw.githubusercontent.com/nodejs/Release/main/schedule.jsonโ†ฉ
  15. CISA. "Known Exploited Vulnerabilities Catalog" (Google Brotli Unchecked Return Value Vulnerability, dateAdded 2026-10-27, dueDate 2026-11-10). https://www.cisa.gov/known-exploited-vulnerabilities-catalogโ†ฉ
  16. Node.js. "Wednesday, November 11, 2026 Security Releases" (์‚ฌ์ „ ๊ณต์ง€. ์ตœ๊ณ  ์‹ฌ๊ฐ๋„ HIGH, CVE ๋ชฉ๋ก ๋ฏธ๊ธฐ์žฌ). https://nodejs.org/en/blog/vulnerability/november-2026-security-releasesโ†ฉ

@leekh8
๋ณด์•ˆ, ์›น ๊ฐœ๋ฐœ, Python์„ ๋‹ค๋ฃจ๋Š” ๊ธฐ์ˆ  ๋ธ”๋กœ๊ทธ