A TFTP server that answers with a short ERROR packet makes the client read up to 64 bytes past the
received datagram.
Each receive path checks only that the datagram is at least four bytes long (nxd_tftp_client.c:1229,
1521, 1984). When the opcode is NX_TFTP_CODE_ERROR the message string is copied with a loop whose
only limits are the destination buffer and a NUL byte:
```c
/* addons/tftp/nxd_tftp_client.c:1769 */
for (i = 0; (i < (sizeof(tftp_client_ptr -> nx_tftp_client_error_string) - 1)) && (*buffer_ptr); i++)
```
Nothing compares `buffer_ptr` against `nx_packet_append_ptr`. An ERROR packet that carries no
terminating NUL, which a server controls completely, walks the loop off the end of the packet until
it happens to meet a zero byte or fills the 64 byte destination.
```
ERROR: AddressSanitizer: heap-buffer-overflow
READ of size 1 at 0x60d0000000c8 thread T4
#0 _nxd_tftp_client_file_read addons/tftp/nxd_tftp_client.c:1769
0x60d0000000c8 is 0 bytes to the right of 136-byte region
```
The open path has the same loop at :1327 and reports the same way. What is read lands in
`nx_tftp_client_error_string`, which the application is expected to display or log, so adjacent
packet pool memory ends up in whatever the device does with the error text.
Add `(buffer_ptr < packet_ptr -> nx_packet_append_ptr)` to the loop condition in all three paths.
GHSA-5cxq-44w6-64mx
A TFTP server that answers with a short ERROR packet makes the client read up to 64 bytes past...
https://github.com/advisories/GHSA-5cxq-44w6-64mxA TFTP server that answers with a short ERROR packet makes the client read up to 64 bytes past the
received datagram.
Each receive path checks only that the datagram is at least four bytes long (nxd_tftp_client.c:1229,
1521, 1984). When the opcode is NX_TFTP_CODE_ERROR the message string is copied with a loop whose
only limits are the destination buffer and a NUL byte:
/* addons/tftp/nxd_tftp_client.c:1769 */
for (i = 0; (i < (sizeof(tftp_client_ptr -> nx_tftp_client_error_string) - 1)) && (*buffer_ptr); i++)
Nothing compares buffer_ptr against nx_packet_append_ptr. An ERROR packet that carries no
terminating NUL, which a server controls completely, walks the loop off the end of the packet until
it happens to meet a zero byte or fills the 64 byte destination.
ERROR: AddressSanitizer: heap-buffer-overflow
READ of size 1 at 0x60d0000000c8 thread T4
#0 _nxd_tftp_client_file_read addons/tftp/nxd_tftp_client.c:1769
0x60d0000000c8 is 0 bytes to the right of 136-byte region
The open path has the same loop at :1327 and reports the same way. What is read lands in
nx_tftp_client_error_string, which the application is expected to display or log, so adjacent
packet pool memory ends up in whatever the device does with the error text.
Add (buffer_ptr < packet_ptr -> nx_packet_append_ptr) to the loop condition in all three paths.
Click to expand
{
"dataType": "CVE_RECORD",
"dataVersion": "5.2",
"cveMetadata": {
"cveId": "CVE-2026-102721",
"assignerOrgId": "e51fbebd-6053-4e49-959f-1b94eeb69a2c",
"assignerShortName": "eclipse",
"dateUpdated": "2026-09-29T17:47:12.769Z",
"dateReserved": "2026-09-29T16:15:17.020Z",
"datePublished": "2026-09-29T17:47:12.769Z",
"state": "PUBLISHED"
},
"containers": {
"cna": {
"providerMetadata": {
"orgId": "e51fbebd-6053-4e49-959f-1b94eeb69a2c",
"shortName": "eclipse",
"dateUpdated": "2026-09-29T17:47:12.769Z"
},
"descriptions": [
{
"lang": "en",
"value": "A TFTP server that answers with a short ERROR packet makes the client read up to 64 bytes past the\n\n\n\nreceived datagram.\n\n\n\nEach receive path checks only that the datagram is at least four bytes long (nxd_tftp_client.c:1229,\n\n\n\n1521, 1984). When the opcode is NX_TFTP_CODE_ERROR the message string is copied with a loop whose\n\n\n\nonly limits are the destination buffer and a NUL byte:\n\n\n\n```c\n\n\n\n/* addons/tftp/nxd_tftp_client.c:1769 */\n\n\n\nfor (i = 0; (i < (sizeof(tftp_client_ptr -> nx_tftp_client_error_string) - 1)) && (*buffer_ptr); i++)\n\n\n\n```\n\n\n\nNothing compares `buffer_ptr` against `nx_packet_append_ptr`. An ERROR packet that carries no\n\n\n\nterminating NUL, which a server controls completely, walks the loop off the end of the packet until\n\n\n\nit happens to meet a zero byte or fills the 64 byte destination.\n\n\n\n```\n\n\n\nERROR: AddressSanitizer: heap-buffer-overflow\n\n\n\nREAD of size 1 at 0x60d0000000c8 thread T4\n\n #0 _nxd_tftp_client_file_read addons/tftp/nxd_tftp_client.c:1769\n\n\n0x60d0000000c8 is 0 bytes to the right of 136-byte region\n\n\n\n```\n\n\n\nThe open path has the same loop at :1327 and reports the same way. What is read lands in\n\n\n\n`nx_tftp_client_error_string`, which the application is expected to display or log, so adjacent\n\n\n\npacket pool memory ends up in whatever the device does with the error text.\n\n\n\nAdd `(buffer_ptr < packet_ptr -> nx_packet_append_ptr)` to the loop condition in all three paths.",
"supportingMedia": [
{
"type": "text/html",
"base64": false,
"value": "<p>A TFTP server that answers with a short ERROR packet makes the client read up to 64 bytes past the</p><p>received datagram.</p><p>Each receive path checks only that the datagram is at least four bytes long (nxd_tftp_client.c:1229,</p><p>1521, 1984). When the opcode is NX_TFTP_CODE_ERROR the message string is copied with a loop whose</p><p>only limits are the destination buffer and a NUL byte:</p><p>```c</p><p>/* addons/tftp/nxd_tftp_client.c:1769 */</p><p>for (i = 0; (i < (sizeof(tftp_client_ptr -> nx_tftp_client_error_string) - 1)) && (*buffer_ptr); i++)</p><p>```</p><p>Nothing compares `buffer_ptr` against `nx_packet_append_ptr`. An ERROR packet that carries no</p><p>terminating NUL, which a server controls completely, walks the loop off the end of the packet until</p><p>it happens to meet a zero byte or fills the 64 byte destination.</p><p>```</p><p>ERROR: AddressSanitizer: heap-buffer-overflow</p><p>READ of size 1 at 0x60d0000000c8 thread T4</p><code> #0 _nxd_tftp_client_file_read addons/tftp/nxd_tftp_client.c:1769</code><br><p>0x60d0000000c8 is 0 bytes to the right of 136-byte region</p><p>```</p><p>The open path has the same loop at :1327 and reports the same way. What is read lands in</p><p>`nx_tftp_client_error_string`, which the application is expected to display or log, so adjacent</p><p>packet pool memory ends up in whatever the device does with the error text.</p><p>Add `(buffer_ptr < packet_ptr -> nx_packet_append_ptr)` to the loop condition in all three paths.</p>"
}
]
}
],
"affected": [
{
"vendor": "Eclipse Foundation",
"product": "NetX Duo",
"packageName": "NetX Duo",
"defaultStatus": "unaffected",
"versions": [
{
"version": "0",
"status": "affected",
"versionType": "semver",
"lessThanOrEqual": "6.5.1"
}
]
}
],
"problemTypes": [
{
"descriptions": [
{
"lang": "en",
"description": "CWE-125 Out-of-bounds Read",
"cweId": "CWE-125",
"type": "CWE"
}
]
}
],
"references": [
{
"url": "https://github.com/eclipse-threadx/netxduo/security/advisories/GHSA-wvc9-5m9h-rvxc"
}
],
"metrics": [
{
"format": "CVSS",
"scenarios": [
{
"lang": "en",
"value": "GENERAL"
}
]
}
],
"credits": [
{
"lang": "en",
"value": "L0stHeart",
"type": "reporter"
}
]
}
}
}