Summary
Multiple memory safety and logic vulnerabilities exist in microcoap's CoAP option parsing and serialization code. The most severe is a buffer overflow in coap_build() that enables remote code execution on microcontroller targets.
Vulnerability 1: coap_build() Buffer Overflow (CWE-787, Critical)
File: coap.c, function coap_build(), lines 295-331
The bounds check in the option serialization loop is insufficient:
if (((size_t)(p-buf)) > *buflen) // (1) uses > instead of >=
return COAP_ERR_BUFFER_TOO_SMALL;
// After this check passes, the following writes have NO bounds checks:
*p++ = (0xFF & (delta << 4 | len)); // 1 byte
if (delta == 13)
*p++ = (optDelta - 13); // up to 1 byte
else if (delta == 14) {
*p++ = ((optDelta-269) >> 8); // up to 2 bytes
*p++ = (0xFF & (optDelta-269));
}
// ... same pattern for len ...
memcpy(p, pkt->opts[i].buf.p, pkt->opts[i].buf.len); // N bytes, no check
Problems:
- The check uses
> instead of >= (off-by-one: when p-buf == *buflen, p is already past the buffer)
- The check is performed before writing but doesn't account for the bytes about to be written (1 header + up to 4 extended bytes + option value)
On the primary deployment targets (Arduino/ESP8266/ESP32 with 64-256 byte buffers), a crafted CoAP request with many large options causes coap_build() to write past the output buffer when constructing a response.
Impact: Heap/stack buffer overflow → remote code execution on microcontrollers (no ASLR, no stack canaries, no DEP on most MCUs).
Vulnerability 2: Option Length uint16_t Overflow (CWE-190, High)
File: coap.c, function coap_parseOption(), line 130
uint16_t len, delta;
// ...
len = ((p[1] << 8) | p[2]) + 269; // result up to 65804, wraps in uint16_t
When the extended length bytes yield a value where (p[1] << 8) | p[2] > 65266, the result overflows uint16_t. The length wraps to a small value, the bounds check on line 137 passes, and only the wrapped number of bytes are consumed. The remaining bytes of the actual option value are misinterpreted as subsequent option headers — cascading parse corruption from a single crafted packet.
Same issue affects delta on lines 109/148.
Vulnerability 3: Option Number Truncation (CWE-681, High)
File: coap.c line 141, coap.h line 40
Already reported as issue #47 (2019, unfixed). coap_option_t.num is uint8_t but CoAP option numbers go up to 65804. Assignment option->num = delta + *running_delta silently truncates. An attacker can make option 267 appear as option 11 (URI-Path), bypassing endpoint routing and any wire-level option filtering.
Additional Issues
- Finding 7 (Medium): Options beyond MAXOPT (16) silently dropped — security-relevant options ignored
- Finding 8 (Medium): Token length
size_t → uint8_t truncation in coap_make_response()
Suggested Fixes
- coap_build(): Before writing each option, compute total bytes needed and verify
(p - buf) + total_needed <= *buflen
- coap_parseOption(): Change
delta and len to uint32_t
- coap_option_t.num: Change from
uint8_t to uint16_t
Summary
Multiple memory safety and logic vulnerabilities exist in microcoap's CoAP option parsing and serialization code. The most severe is a buffer overflow in
coap_build()that enables remote code execution on microcontroller targets.Vulnerability 1: coap_build() Buffer Overflow (CWE-787, Critical)
File:
coap.c, functioncoap_build(), lines 295-331The bounds check in the option serialization loop is insufficient:
Problems:
>instead of>=(off-by-one: whenp-buf == *buflen,pis already past the buffer)On the primary deployment targets (Arduino/ESP8266/ESP32 with 64-256 byte buffers), a crafted CoAP request with many large options causes
coap_build()to write past the output buffer when constructing a response.Impact: Heap/stack buffer overflow → remote code execution on microcontrollers (no ASLR, no stack canaries, no DEP on most MCUs).
Vulnerability 2: Option Length uint16_t Overflow (CWE-190, High)
File:
coap.c, functioncoap_parseOption(), line 130When the extended length bytes yield a value where
(p[1] << 8) | p[2] > 65266, the result overflowsuint16_t. The length wraps to a small value, the bounds check on line 137 passes, and only the wrapped number of bytes are consumed. The remaining bytes of the actual option value are misinterpreted as subsequent option headers — cascading parse corruption from a single crafted packet.Same issue affects
deltaon lines 109/148.Vulnerability 3: Option Number Truncation (CWE-681, High)
File:
coap.cline 141,coap.hline 40Already reported as issue #47 (2019, unfixed).
coap_option_t.numisuint8_tbut CoAP option numbers go up to 65804. Assignmentoption->num = delta + *running_deltasilently truncates. An attacker can make option 267 appear as option 11 (URI-Path), bypassing endpoint routing and any wire-level option filtering.Additional Issues
size_t→uint8_ttruncation incoap_make_response()Suggested Fixes
(p - buf) + total_needed <= *buflendeltaandlentouint32_tuint8_ttouint16_t