GHSA-4x76-j955-qhq2: Out-of-bounds Write via the TLS 1.3 Handshake Message Cache in NetX Secure
GHSA ID |
|
|---|---|
CVE ID |
CVE‑2026‑103416 |
Severity |
Critical |
CVSS score |
9.8 ( |
CWE |
|
Published |
2026‑10‑02 |
Last updated |
2026‑10‑02 |
Description
Summary
_nx_secure_tls_send_handshake_record caches every outgoing handshake message in a fixed 500 byte array that lives inside the TLS session control block, and the copy was never bounded against that array. A handshake message larger than the cache writes past it and on into the rest of the session control block, which holds pointers. A malicious or compromised server can make a TLS 1.3 client produce such a message before certificate authentication completes, so no server certificate is needed to reach it.
Details
The cache is nx_secure_tls_handshake_cache, a UCHAR array of 500 bytes declared inside nx_secure_tls_key_material, which is part of the TLS session control block. _nx_secure_tls_send_handshake_record fills it whenever the hash method is not yet known, which under TLS 1.3 is every message sent before a ciphersuite has been chosen, and on every ClientHello regardless of protocol version.
The function walks the outgoing packet chain, copies each fragment at a running offset, and advances both that offset and the recorded cache length by the fragment length. Neither the fragment length nor either running total was compared against the capacity of the destination, so the copy continued past the end of the array.
The path a hostile peer takes is the HelloRetryRequest. A TLS 1.3 client that receives one copies the server’s cookie into its second ClientHello, and the peer chooses that cookie’s length and contents. The cookie is bounded only by the room left in the TLS packet buffer, which is typically well over a kilobyte. With the base ClientHello measured at 233 bytes in the regression suite, a cookie beyond roughly 261 bytes is enough to exceed the cache.
Integrators who have already applied the fix for GHSA-5pv3-rhf5-gwgq are not covered by it. That change bounds the cookie against the room left in the outgoing packet, which is a different and larger limit than the capacity of this cache, so an oversized ClientHello still overruns the cache here.
Impact
A peer that the client has not yet authenticated controls both the length and the contents of a write that runs past a fixed array and into the rest of the TLS session control block. That structure holds pointers, including the remote certificate list head, so the consequences range from a crash to corruption of data the handshake subsequently dereferences. What bounds it is object placement: how far the write reaches, and what it lands on, depends on the layout of the session control block in a given build and on whatever memory protection the platform applies.
Affected configurations
A build that defines NX_SECURE_TLS_ENABLE_TLS_1_3, which is off by default, with ECC ciphersuites, which are on by default, acting as a TLS client against a malicious or compromised server. Builds without TLS 1.3 do not reach the HelloRetryRequest path.
Every release up to and including 6.5.1.202602 is affected. The array has been 500 bytes and the copy unbounded since the code was first published.
Severity
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H, 9.8, Critical.
The vector is scored for a build with TLS 1.3 enabled, as described above. No privileges or user interaction are required because an embedded client reaches this by connecting to its configured endpoint, and the attacker’s position is that endpoint or anyone able to impersonate it.
Patches
Fixed in NetX Duo 6.5.2.202603.
The copy now requires room for the fragment at the current offset and returns NX_SECURE_TLS_PACKET_BUFFER_TOO_SMALL before writing anything when it does not fit. Truncating was rejected: the cache is hashed once a ciphersuite fixes the hash method, so a short copy would build the wrong transcript and fail later at Finished with a misleading error. The array size now sits behind NX_SECURE_TLS_HANDSHAKE_CACHE_SIZE so it can be raised where larger handshake messages are expected. The check is not gated on TLS 1.3, because the ClientHello branch is version independent and the TLS 1.2 client drains the same cache.
A regression test, nx_secure_tls_1_3_handshake_cache_overflow_test, drives an oversized HelloRetryRequest through the send path; a second, nx_secure_tls_1_3_hello_retry_cache_overflow_test, covers the client path and asserts that the handshake fails with NX_SECURE_TLS_PACKET_BUFFER_TOO_SMALL and that the cache length never passes its capacity. Both segfault against the unfixed source and pass with the fix.
The pre-existing nx_secure_tls_1_3_hello_retry_cookie_test could not have caught this. Its hand built HelloRetryRequest declares an extensions length two bytes short of the bytes that follow, so the client rejects the message and never builds a second ClientHello. The new tests correct that arithmetic in their own copies.
Not run on hardware.