The TFTP server accepts a DATA datagram of any size. The dispatcher rejects datagrams shorter than
four bytes (nxd_tftp_server.c:1037) and nothing anywhere checks an upper bound, in particular not
against the protocol maximum of 4 + NX_TFTP_FILE_TRANSFER_MAX. Two things follow from that one
missing check, both reachable before any authentication because TFTP has none.
The handler passes `nx_packet_length - 4` straight to FileX:
```c
/* addons/tftp/nxd_tftp_server.c:1863, 1889 */
status = nx_packet_copy(packet_ptr, &temp_ptr,
server_ptr -> nx_tftp_server_packet_pool_ptr, NX_WAIT_FOREVER);
...
fx_file_write(&(client_request_ptr -> nx_tftp_client_request_file),
packet_ptr -> nx_packet_prepend_ptr + 4,
packet_ptr -> nx_packet_length - 4);
```
`nx_packet_length` is the length of a chain, not of one contiguous buffer, so FileX copies past the
end of the first packet:
```
ERROR: AddressSanitizer: heap-buffer-overflow
READ of size 1280 at 0x621000001108 thread T5
#0 __interceptor_memcpy
#1 _fx_utility_memory_copy filex/common/src/fx_utility_memory_copy.c:78
0x621000001108 is 0 bytes to the right of 4104-byte region
```
Those bytes are written into the file the attacker is uploading, and a TFTP read request hands them
back, so this is a memory disclosure with a convenient retrieval channel.
The same datagram also wedges the server. `nx_packet_copy` at :1863 needs
ceil(nx_packet_length / pool_payload) packets and asks for them with NX_WAIT_FOREVER, so when the
attacker sizes the datagram beyond what the pool holds, the server thread suspends and never
returns. A liveness probe after one such datagram times out with the pool at 0 of 12 packets and
the server thread suspended, and no later client is served.
Reject `nx_packet_length > 4 + NX_TFTP_FILE_TRANSFER_MAX` in the DATA branch before either call,
and use a bounded wait rather than NX_WAIT_FOREVER for the copy.
GHSA-fhxv-gc8j-2f6h
The TFTP server accepts a DATA datagram of any size. The dispatcher rejects datagrams shorter...
https://github.com/advisories/GHSA-fhxv-gc8j-2f6hThe TFTP server accepts a DATA datagram of any size. The dispatcher rejects datagrams shorter than
four bytes (nxd_tftp_server.c:1037) and nothing anywhere checks an upper bound, in particular not
against the protocol maximum of 4 + NX_TFTP_FILE_TRANSFER_MAX. Two things follow from that one
missing check, both reachable before any authentication because TFTP has none.
The handler passes nx_packet_length - 4 straight to FileX:
/* addons/tftp/nxd_tftp_server.c:1863, 1889 */
status = nx_packet_copy(packet_ptr, &temp_ptr,
server_ptr -> nx_tftp_server_packet_pool_ptr, NX_WAIT_FOREVER);
...
fx_file_write(&(client_request_ptr -> nx_tftp_client_request_file),
packet_ptr -> nx_packet_prepend_ptr + 4,
packet_ptr -> nx_packet_length - 4);
nx_packet_length is the length of a chain, not of one contiguous buffer, so FileX copies past the
end of the first packet:
ERROR: AddressSanitizer: heap-buffer-overflow
READ of size 1280 at 0x621000001108 thread T5
#0 __interceptor_memcpy
#1 _fx_utility_memory_copy filex/common/src/fx_utility_memory_copy.c:78
0x621000001108 is 0 bytes to the right of 4104-byte region
Those bytes are written into the file the attacker is uploading, and a TFTP read request hands them
back, so this is a memory disclosure with a convenient retrieval channel.
The same datagram also wedges the server. nx_packet_copy at :1863 needs
ceil(nx_packet_length / pool_payload) packets and asks for them with NX_WAIT_FOREVER, so when the
attacker sizes the datagram beyond what the pool holds, the server thread suspends and never
returns. A liveness probe after one such datagram times out with the pool at 0 of 12 packets and
the server thread suspended, and no later client is served.
Reject nx_packet_length > 4 + NX_TFTP_FILE_TRANSFER_MAX in the DATA branch before either call,
and use a bounded wait rather than NX_WAIT_FOREVER for the copy.
Click to expand
{
"dataType": "CVE_RECORD",
"dataVersion": "5.2",
"cveMetadata": {
"cveId": "CVE-2026-102713",
"assignerOrgId": "e51fbebd-6053-4e49-959f-1b94eeb69a2c",
"assignerShortName": "eclipse",
"dateUpdated": "2026-09-29T17:40:40.067Z",
"dateReserved": "2026-09-29T16:15:09.632Z",
"datePublished": "2026-09-29T17:40:40.067Z",
"state": "PUBLISHED"
},
"containers": {
"cna": {
"providerMetadata": {
"orgId": "e51fbebd-6053-4e49-959f-1b94eeb69a2c",
"shortName": "eclipse",
"dateUpdated": "2026-09-29T17:40:40.067Z"
},
"descriptions": [
{
"lang": "en",
"value": "The TFTP server accepts a DATA datagram of any size. The dispatcher rejects datagrams shorter than\n\n\n\nfour bytes (nxd_tftp_server.c:1037) and nothing anywhere checks an upper bound, in particular not\n\n\n\nagainst the protocol maximum of 4 + NX_TFTP_FILE_TRANSFER_MAX. Two things follow from that one\n\n\n\nmissing check, both reachable before any authentication because TFTP has none.\n\n\n\nThe handler passes `nx_packet_length - 4` straight to FileX:\n\n\n\n```c\n\n\n\n/* addons/tftp/nxd_tftp_server.c:1863, 1889 */\n\n\n\nstatus = nx_packet_copy(packet_ptr, &temp_ptr,\n\n server_ptr -> nx_tftp_server_packet_pool_ptr, NX_WAIT_FOREVER);\n\n\n...\n\n\n\nfx_file_write(&(client_request_ptr -> nx_tftp_client_request_file),\n\n packet_ptr -> nx_packet_prepend_ptr + 4,\n packet_ptr -> nx_packet_length - 4);\n\n\n```\n\n\n\n`nx_packet_length` is the length of a chain, not of one contiguous buffer, so FileX copies past the\n\n\n\nend of the first packet:\n\n\n\n```\n\n\n\nERROR: AddressSanitizer: heap-buffer-overflow\n\n\n\nREAD of size 1280 at 0x621000001108 thread T5\n\n #0 __interceptor_memcpy\n #1 _fx_utility_memory_copy filex/common/src/fx_utility_memory_copy.c:78\n\n\n0x621000001108 is 0 bytes to the right of 4104-byte region\n\n\n\n```\n\n\n\nThose bytes are written into the file the attacker is uploading, and a TFTP read request hands them\n\n\n\nback, so this is a memory disclosure with a convenient retrieval channel.\n\n\n\nThe same datagram also wedges the server. `nx_packet_copy` at :1863 needs\n\n\n\nceil(nx_packet_length / pool_payload) packets and asks for them with NX_WAIT_FOREVER, so when the\n\n\n\nattacker sizes the datagram beyond what the pool holds, the server thread suspends and never\n\n\n\nreturns. A liveness probe after one such datagram times out with the pool at 0 of 12 packets and\n\n\n\nthe server thread suspended, and no later client is served.\n\n\n\nReject `nx_packet_length > 4 + NX_TFTP_FILE_TRANSFER_MAX` in the DATA branch before either call,\n\n\n\nand use a bounded wait rather than NX_WAIT_FOREVER for the copy.",
"supportingMedia": [
{
"type": "text/html",
"base64": false,
"value": "<p>The TFTP server accepts a DATA datagram of any size. The dispatcher rejects datagrams shorter than</p><p>four bytes (nxd_tftp_server.c:1037) and nothing anywhere checks an upper bound, in particular not</p><p>against the protocol maximum of 4 + NX_TFTP_FILE_TRANSFER_MAX. Two things follow from that one</p><p>missing check, both reachable before any authentication because TFTP has none.</p><p>The handler passes `nx_packet_length - 4` straight to FileX:</p><p>```c</p><p>/* addons/tftp/nxd_tftp_server.c:1863, 1889 */</p><p>status = nx_packet_copy(packet_ptr, &temp_ptr,</p><code> server_ptr -> nx_tftp_server_packet_pool_ptr, NX_WAIT_FOREVER);</code><br><p>...</p><p>fx_file_write(&(client_request_ptr -> nx_tftp_client_request_file),</p><code> packet_ptr -> nx_packet_prepend_ptr + 4,</code><br><code> packet_ptr -> nx_packet_length - 4);</code><br><p>```</p><p>`nx_packet_length` is the length of a chain, not of one contiguous buffer, so FileX copies past the</p><p>end of the first packet:</p><p>```</p><p>ERROR: AddressSanitizer: heap-buffer-overflow</p><p>READ of size 1280 at 0x621000001108 thread T5</p><code> #0 __interceptor_memcpy</code><br><code> #1 _fx_utility_memory_copy filex/common/src/fx_utility_memory_copy.c:78</code><br><p>0x621000001108 is 0 bytes to the right of 4104-byte region</p><p>```</p><p>Those bytes are written into the file the attacker is uploading, and a TFTP read request hands them</p><p>back, so this is a memory disclosure with a convenient retrieval channel.</p><p>The same datagram also wedges the server. `nx_packet_copy` at :1863 needs</p><p>ceil(nx_packet_length / pool_payload) packets and asks for them with NX_WAIT_FOREVER, so when the</p><p>attacker sizes the datagram beyond what the pool holds, the server thread suspends and never</p><p>returns. A liveness probe after one such datagram times out with the pool at 0 of 12 packets and</p><p>the server thread suspended, and no later client is served.</p><p>Reject `nx_packet_length > 4 + NX_TFTP_FILE_TRANSFER_MAX` in the DATA branch before either call,</p><p>and use a bounded wait rather than NX_WAIT_FOREVER for the copy.</p>"
}
]
}
],
"affected": [
{
"vendor": "Eclipse Foundation",
"product": "NetX Duo",
"packageName": "NetX Duo",
"defaultStatus": "unaffected",
"versions": [
{
"version": "0",
"status": "affected",
"versionType": "semver",
"lessThanOrEqual": "6.5.1.202602"
}
]
}
],
"problemTypes": [
{
"descriptions": [
{
"lang": "en",
"description": "CWE-125 Out-of-bounds Read",
"cweId": "CWE-125",
"type": "CWE"
}
]
},
{
"descriptions": [
{
"lang": "en",
"description": "CWE-770 Allocation of Resources Without Limits or Throttling",
"cweId": "CWE-770",
"type": "CWE"
}
]
}
],
"references": [
{
"url": "https://github.com/eclipse-threadx/netxduo/security/advisories/GHSA-wr79-332c-ff8f"
}
],
"metrics": [
{
"format": "CVSS",
"scenarios": [
{
"lang": "en",
"value": "GENERAL"
}
]
}
],
"credits": [
{
"lang": "en",
"value": "L0stHeart",
"type": "reporter"
}
]
}
}
}