A newly disclosed critical pre-authentication heap buffer overflow in NGINX’s Stream module, tracked as CVE-2026-42533, could allow unauthenticated remote attackers to crash worker processes and potentially achieve arbitrary code execution.
The vulnerability carries a CVSS v4.0 score of 9.2 and affects nearly every deployed NGINX Open Source version from 0.9.6 through 1.31.2, along with NGINX Plus builds prior to 37.0.3.1 and R36 P7.
The flaw resides in ngx_stream_script.c (line 940) within the ngx_stream_script_copy_capture_code function, which handles regex capture copying during complex value evaluation in the Stream module.
NGINX Heap Overflow Flaw
NGINX’s ssl_preread module extracts TLS handshake metadata including the Server Name Indication (SNI) into internal variables before TLS termination occurs, so these values can be used in stream-level directives like return.
When such a value is processed as a “complex value,” the script engine runs a two-pass algorithm: it first calculates the required buffer length, then performs the actual data copy.
The vulnerability arises because evaluating a regex-based variable (such as one defined in a map block) between these two passes can mutate the global PCRE capture state.
This class of two-pass timing inconsistency in NGINX’s script engine has proven to be a recurring root-cause pattern, as similar logic flaws in the HTTP rewrite module’s script engine were separately identified in CVE-2026-42945, dubbed “Nginx Rift”.
In that case, the length-calculation pass and copy pass diverged due to state changes in the engine, leading to comparable heap corruption.
An attacker connecting to a stream listener with ssl_preread on and a configuration combining a regex map on $ssl_preread_server_name with a return directive referencing both a capture group and the mapped variable can trigger the bug.
By sending a crafted TLS ClientHello with an oversized SNI field, the attacker forces a mismatch: the engine calculates a short buffer during the length pass, but the capture state updates before the copy pass, causing more data to be written than was allocated.
Because this occurs entirely during ssl_preread, the corruption happens before any TLS handshake completion or authentication check, making internet-facing TCP/UDP proxies particularly exposed.
Proof-of-Concept
Markakd validated the flaw using an AddressSanitizer-instrumented NGINX build with stream_ssl_preread_module enabled. A Python-based PoC sent a TLS ClientHello containing a 1,000-byte SNI hostname to a server configured with map $ssl_preread_server_name $m { ~^(.*)$ ok; } and return "$1$m".
The test confirmed a heap-buffer-overflow WRITE of size 1000 bytes, occurring exactly one byte past a 256-byte heap region allocated via ngx_palloc_block, with the crash traced directly to the memcpy call inside ngx_stream_script_copy_capture_code at line 940.
Mitigation
Administrators using regex-based maps on preread variables within stream {} blocks should audit configurations, restrict exposure of such listeners, and monitor for upstream NGINX patches addressing script-engine capture-state handling, given the precedent set by similar two-pass overflow fixes in the HTTP module.
Cut SOC investigation blind spots and contain threats earlier to reduce response costs and business disruption with ANY.RUN.