Security Advisory — ByteScan Security Research Lab

BSR-2026-ZEPHYR-001
Two Vulnerabilities in Zephyr RTOS HTTP Subsystem

High — HPACK Decoder UB Medium — Null Ptr Arithmetic
Report ID
BSR-2026-ZEPHYR-001
CVE IDs
Pending assignment (disclosed to Zephyr Security Team)
Affected
Zephyr RTOS (zephyrproject-rtos/zephyr) — HTTP subsystem
Components
subsys/net/lib/http/http_hpack.c — subsys/net/lib/http/http_compression.c
Attack vector
Network — unauthenticated, no special configuration
Discovered by
Dr. Mohammadreza Ashouri — ByteScan Security Research Lab
Published
2026-09-05

Overview

Static code analysis of the Zephyr RTOS HTTP subsystem identified two confirmed vulnerabilities in live, network-facing code. Both are reachable without authentication on any Zephyr device running the HTTP server (CONFIG_NET_HTTP_SERVER). Zephyr is a widely deployed open-source RTOS used across IoT, embedded, and industrial systems with an active CVE program maintained by the Linux Foundation.

Findings

BSR-001 Undefined Behavior via Shift-by-32 in HPACK Integer Decoder High

File: subsys/net/lib/http/http_hpack.c:192
CWE: CWE-190 (Integer Overflow) / CWE-758 (Undefined Behavior)
CVSS v3.1 (est.): CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H — 7.5 High

Description

The HPACK integer decoder uses a guard condition of m > sizeof(uint32_t) * 8 (i.e., m > 32) to detect excessive shift counts. However the shift 1 << m executes when m == 32 before the guard fires at m == 35. Left-shifting a signed 32-bit integer by 32 bits is undefined behavior under C11 §6.5.7.

HPACK is the header compression format for HTTP/2. Every incoming HTTP/2 HEADERS frame passes through this decoder, making the path reachable from any network-accessible Zephyr device running the HTTP server.

Vulnerable Code

/* http_hpack.c:183-198 */
if (m > sizeof(uint32_t) * 8) {  /* fires at m==35, not m==32 */
    return -EBADMSG;
}
*value += (*buf & ~HPACK_INTEGER_CONTINUATION_FLAG) * (1 << m);
/* ^^^ when m==32: shift of signed int by 32 = UB (C11 §6.5.7) */
m += 7;
Fix: Change m > sizeof(uint32_t) * 8 to m >= sizeof(uint32_t) * 8. Also replace the literal 1 with 1U to make the shift unsigned.

Trigger

Send an HTTP/2 HEADERS frame containing an HPACK-encoded integer that requires 5 continuation bytes, advancing m through 7, 14, 21, 28, and then to 35. The guard does not fire at m == 32, so the UB shift executes. No authentication or special headers required.

On embedded targets compiled with optimization, compilers routinely exploit signed shift UB to eliminate surrounding bounds checks, potentially escalating from a logic error to memory corruption or control flow hijack.
BSR-002 Null Pointer Arithmetic in HTTP Accept-Encoding Parser Medium

File: subsys/net/lib/http/http_compression.c:59,71
CWE: CWE-476 (NULL Pointer Dereference)
CVSS v3.1 (est.): CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H — 7.5 High

Description

In the Accept-Encoding header parser, end is set to NULL before start is advanced using start = end + 1. The assignment order is reversed: start must be updated first, then end nulled. This pattern appears twice in the same loop — once in the oversized-token branch and once after every valid token boundary.

The second instance triggers on any HTTP request with a multi-value Accept-Encoding header, which is sent by all major browsers and HTTP clients (Accept-Encoding: gzip, deflate, br).

Vulnerable Code

/* http_compression.c:56-73 */
if (end - start > HTTP_COMPRESSION_MAX_STRING_LEN) {
    end = NULL;
    start = end + 1;  /* BUG: NULL + 1, produces 0x1 */
    continue;
}
memcpy(strbuf, start, end - start);
/* ... */
end = NULL;
start = end + 1;  /* BUG: same mistake after every valid token */
Fix: Swap the assignment order in both locations: start = end + 1; then end = NULL;

Trigger

Any HTTP GET request with Accept-Encoding: gzip, deflate triggers the second instance on the first token boundary. No special conditions required. A standard browser request is sufficient.

On embedded RTOS targets without memory protection, dereferencing a near-null pointer (0x1) as a memcpy source typically causes an immediate hard fault or silent memory corruption of the receive buffer.

Discovery Method

Both findings were identified through static code analysis of the Zephyr RTOS mainline repository. The toolchain used: Semgrep (p/c + p/security-audit, 90 findings, all triaged to false positives) and Cppcheck 2.21.0 (--enable=all, findings manually verified against live code paths). Dead code and macro-generated false positives were excluded before reporting.

Further information on ByteScan's research tooling, including the VULCAN LLM-guided mutation fuzzer, is available at bytescan.net/vulcan.html.

Disclosure Timeline

References

Zephyr RTOS repository: github.com/zephyrproject-rtos/zephyr
Zephyr security policy: docs.zephyrproject.org/latest/security/reporting.html

Credits

Discovered and reported by Dr. Mohammadreza Ashouri, ByteScan Security Research Lab — audit@bytescan.net — bytescan.net — linkedin.com/in/drashouri