CVE-2026-29972 Overview
CVE-2026-29972 is a stack-based buffer overflow [CWE-121] in the nanoMODBUS library through version v1.22.0. The flaw resides in the recv_read_registers_res() function in nanomodbus.c. When a Modbus TCP client calls nmbs_read_holding_registers() or nmbs_read_input_registers(), the library copies register data from the server response into the caller-provided buffer using the response's byte_count field without first validating it against the requested register quantity. A malicious Modbus TCP server can return byte_count=250 (125 registers) regardless of what the client requested, overflowing the destination buffer by up to 248 bytes with attacker-controlled data. This condition can lead to remote code execution against vulnerable Modbus clients.
Critical Impact
A malicious Modbus TCP server can corrupt the stack of any client using nanoMODBUS to read holding or input registers, enabling potential remote code execution against industrial control system clients.
Affected Products
- nanoMODBUS library through version v1.22.0
- Applications linking nanoMODBUS that call nmbs_read_holding_registers()
- Applications linking nanoMODBUS that call nmbs_read_input_registers()
Discovery Timeline
- 2026-05-08 - CVE CVE-2026-29972 published to NVD
- 2026-05-13 - Last updated in NVD database
Technical Details for CVE-2026-29972
Vulnerability Analysis
nanoMODBUS is a compact Modbus client and server C library used in embedded systems and industrial control environments. The library implements Modbus TCP and RTU framing in a single source file, nanomodbus.c. The vulnerable code path handles server responses to function codes 0x03 (Read Holding Registers) and 0x04 (Read Input Registers).
When a client issues a register-read request, the library sends the requested quantity in the request frame and then parses the server response. The response carries a byte_count field that should equal 2 * quantity. The implementation reads byte_count bytes directly from the wire into the caller-supplied register buffer before comparing byte_count against the original requested quantity. Because the buffer is sized for the requested quantity, an oversized byte_count overruns adjacent stack memory.
Root Cause
The root cause is missing input validation on a length field controlled by an untrusted peer. The function recv_read_registers_res() trusts the byte_count byte from the server response and uses it as the copy length into a fixed-size stack buffer sized for the client's requested register count. The validation that byte_count matches 2 * quantity occurs only after the copy completes, which is too late to prevent corruption.
Attack Vector
Exploitation requires the victim client to connect to an attacker-controlled or compromised Modbus TCP server, or for an attacker positioned in the network path to inject a crafted response. Once the client issues a read request, the attacker responds with a frame where byte_count=250, supplying up to 250 bytes of payload. Of that payload, up to 248 bytes write past the end of the caller's buffer, overwriting saved registers, return addresses, or adjacent locals on the stack. With control over the overflowed bytes, an attacker can pursue stack-based code execution techniques against the client process.
A public proof of concept is referenced in the GitHub Gist PoC. The vulnerable code region is visible in the nanoMODBUS source on GitHub.
Detection Methods for CVE-2026-29972
Indicators of Compromise
- Modbus TCP response frames where the byte_count field exceeds 2 * requested_quantity from the preceding request.
- Modbus TCP responses to function codes 0x03 or 0x04 carrying byte_count=250 when the client requested fewer registers.
- Unexpected crashes, segmentation faults, or abnormal termination in client processes that link nanoMODBUS shortly after Modbus polling cycles.
- Outbound Modbus TCP sessions from operator workstations or historians to unrecognized server endpoints.
Detection Strategies
- Deploy deep packet inspection on TCP port 502 to flag responses where byte_count does not equal 2 * quantity from the matched request.
- Hunt for processes statically linked against nanoMODBUS by scanning binaries for the symbol recv_read_registers_res or strings from nanomodbus.c.
- Correlate ICS network captures with endpoint crash telemetry to identify clients targeted by malformed register responses.
Monitoring Recommendations
- Enable protocol-aware logging on industrial firewalls and OT IDS sensors for Modbus TCP read transactions.
- Track Modbus client-to-server pairings and alert when a known client connects to an unapproved server IP.
- Forward endpoint crash dumps from engineering workstations and SCADA hosts to a central analysis pipeline for triage.
How to Mitigate CVE-2026-29972
Immediate Actions Required
- Inventory all applications and firmware images that embed nanoMODBUS at or below version v1.22.0.
- Restrict Modbus TCP client traffic so that vulnerable clients only connect to trusted, authenticated server endpoints on isolated OT network segments.
- Block inbound and outbound TCP 502 traffic across IT/OT boundaries unless explicitly required.
- Disable or replace integrations that poll holding or input registers from untrusted servers until the library is patched.
Patch Information
At the time of publication, no fixed release is referenced in the NVD entry. Monitor the nanoMODBUS project on GitHub for upstream commits addressing the validation order in recv_read_registers_res(). Applications that vendor nanoMODBUS should add a check ensuring byte_count == 2 * quantity before copying response data, and treat any mismatch as a protocol error that aborts the transaction.
Workarounds
- Patch the local copy of nanomodbus.c to validate byte_count against the requested quantity before any memory copy.
- Wrap nanoMODBUS calls so that requests are issued only to allow-listed server addresses authenticated at the network layer.
- Place an OT-aware proxy or firewall between clients and servers that enforces Modbus frame conformance and drops responses with inconsistent byte_count values.
- Compile dependent binaries with stack protection flags such as -fstack-protector-strong and position-independent execution to raise the cost of exploitation.
# Configuration example: block Modbus TCP egress except to approved servers
iptables -A OUTPUT -p tcp --dport 502 -d 10.20.30.40 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 502 -j DROP
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

