GHSA-9v23-qwp9-2q3h: NetX Duo MQTT client leaks one receive packet per malformed PUBLISH
GHSA ID |
|
|---|---|
CVE ID |
CVE‑2026‑102762 |
Severity |
Medium |
CVSS score |
5.9 ( |
CWE |
|
Published |
2026‑10‑02 |
Last updated |
2026‑10‑02 |
Affected packages
| Package | Vulnerable versions | Patched versions |
|---|---|---|
NetX Duo |
>= 6.0, ⇐ 6.5.1.202602 |
6.5.2.202603 |
Description
Summary
The NetX Duo MQTT client leaks the packet carrying a malformed PUBLISH message. Each malformed PUBLISH costs one packet, or one chain of packets, from the network driver’s receive pool, and nothing returns it. A peer that can deliver a few dozen such messages exhausts the pool and stops all inbound network traffic on the device until it is rebooted.
Details
_nxd_mqtt_process_publish() returns NX_TRUE when it has taken ownership of the packet, NX_FALSE when it has not, and NXD_MQTT_INVALID_PACKET when the PUBLISH is malformed: a remaining length below 2, a topic length that runs past the end of the message, or a QoS 1 or 2 message with no room for the packet identifier.
Its caller, _nxd_mqtt_packet_receive_process(), stored the return value directly in packet_consumed and released the packet only when that value was zero. NXD_MQTT_INVALID_PACKET is non-zero, so a malformed PUBLISH was treated as consumed: parsing stopped, the release was skipped, and no queue or other structure held a reference to the packet.
The leaked packet is the one the client received, before any copy into the MQTT client’s own pool, so it comes from the pool the network driver receives into, which is usually the IP instance’s default pool. The path is the same over plain TCP, TLS and WebSocket. The smallest malformed message is three bytes: 30 01 00.
Impact
An attacker gets a persistent denial of service. The exhausted pool is normally the one every inbound packet on the IP instance is received into, so not only MQTT stops: every other protocol on the device stops receiving as well. The pool does not recover while the device keeps running. Confidentiality and integrity are not affected.
The attacker must be the broker the client is connected to, or, on a plain TCP connection, able to inject data into that TCP stream. A conforming broker parses every PUBLISH it receives and re-encodes the ones it forwards, so another client of the same broker cannot deliver malformed framing through it.
Affected configurations
Every build of the MQTT client add-on (addons/mqtt), in every configuration: plain TCP, TLS (NX_SECURE_ENABLE), WebSocket (NXD_MQTT_OVER_WEBSOCKET) and the cloud module build (NXD_MQTT_CLOUD_ENABLE).
All NetX Duo releases from 6.0 up to and including 6.5.1.202602. The defect has been present since the first public release of the MQTT client.
Severity
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H, 5.9 (Medium).
Attack complexity is High because the attacker has to be the broker the device chose to connect to, or on the network path between them; a broker cannot be made to relay the malformed message from somewhere else. No privileges are required of an on-path attacker on a plain connection.
Patches
Fixed in NetX Duo 6.5.2.202603. _nxd_mqtt_packet_receive_process() treats a packet as consumed only when _nxd_mqtt_process_publish() returns NX_TRUE. On NXD_MQTT_INVALID_PACKET it stops parsing the rest of the chain and releases the packet. It does not skip the malformed message and carry on with the next one, because MQTT 3.1.1 section 4.8 expects a client to treat a malformed packet as a protocol error. Well-formed PUBLISH messages are handled exactly as before.
A regression test sends one PUBLISH for each of the three malformed forms, followed by a well-formed one, over plain TCP and over TLS. It checks that only the well-formed message is delivered, that the client keeps receiving, and that the packet pool is full once the client is deleted. Without the fix it fails the pool check in both configurations.