Tasmota fetch_jpg() Integer Wraparound to Heap Corruption (CVE-2026-38427)
by Saidakbarxon Maxsudxonov (sermikr0) · 2026-07-05
- Severity
- Critical
- CVE
- CVE-2026-38427
- Category
- network
- Affected product
- Arendst Tasmota (ESP32 firmware)
- Affected versions
- <= 15.3.0.3
- Disclosed
- 2026-07-05
- Patch status
- patched
References
Archive entry
intelseclab/poc-archiveMetadata
| Field | Value |
|---|---|
| Date Added | 2026-07-05 |
| Last Updated | 2026-05 |
| Author / Researcher | Saidakbarxon Maxsudxonov (sermikr0) |
| CVE / Advisory | CVE-2026-38427 |
| Category | network |
| Severity | Critical |
| CVSS Score | 9.8 (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H) |
| Status | PoC |
| Tags | tasmota, esp32, iot, integer-overflow, heap-corruption, rce, mjpeg, scripter |
| Related | CVE-2026-38422, CVE-2026-38426 |
Affected Target
| Field | Value |
|---|---|
| Software / System | Arendst Tasmota (ESP32 firmware) |
| Versions Affected | <= 15.3.0.3 |
| Language / Platform | Python (PoC server) targeting C++/Arduino ESP32 firmware |
| Authentication Required | No (device must be scripted to connect to attacker’s MJPEG server) |
| Network Access Required | Yes |
Summary
When fetching subsequent MJPEG frames (case 2) in Tasmota’s scripter driver, fetch_jpg() reads the Content-Length header value via atoi() into a uint16_t variable. Values above 65535 silently wrap around (e.g. 65537 becomes 1), causing the device to allocate a drastically undersized heap buffer and read only that truncated number of bytes from the stream. The remaining, un-consumed bytes are left in the HTTP/WiFi stream buffer, corrupting stream and heap state and leading to a crash or, depending on heap layout, potential remote code execution.
Vulnerability Details
Root Cause
fetch_jpg() case 2 assigns size = atoi(cp + 1) where size is declared uint16_t, silently truncating any Content-Length value greater than 65535 before it is used to malloc() the receive buffer (CWE-190 integer overflow/wraparound leading to undersized allocation).
Attack Vector
- Configure a Tasmota device (via a script using
fetchjp()) to fetch MJPEG frames from an attacker-controlled server, or MITM an existing connection. - Send MJPEG frame headers with
Content-Lengthvalues exceeding 65535 (e.g. 65537, 70000, 131072). - Tasmota allocates a buffer sized to the wrapped
uint16_tvalue and reads only that many bytes, leaving up to 65536+ bytes unread in the stream. - The stale, un-consumed bytes corrupt subsequent stream parsing and heap state, causing a crash or exploitable memory corruption.
Impact
Denial of service (crash/reboot loop) and potential remote code execution on ESP32-based Tasmota devices with scripter support enabled.
Environment / Lab Setup
Target: ESP32 device running Tasmota <= 15.3.0.3 with a script using fetchjp()
Attacker: python3
Proof of Concept
PoC Script
See
CVE-2026-38427_poc.pyin this folder.
| |
The script runs a fake MJPEG HTTP server that sends frame headers with the specified oversized Content-Length value, triggering the uint16_t wraparound and resulting undersized allocation on a connecting Tasmota device.
Detection & Indicators of Compromise
Exception (28): epc1=... ...
Fatal exception ... rebooting
Signs of compromise:
- Device crash/reboot loop shortly after establishing an MJPEG stream connection
- MJPEG server responses with
Content-Lengthvalues above 65535 in captured traffic
Remediation
| Action | Detail |
|---|---|
| Primary fix | Update to Tasmota v15.3.0.4 or later, which uses a wide integer type and validates Content-Length before allocation |
| Interim mitigation | Restrict fetchjp() scripts to trusted MJPEG servers only; disable scripter support if unused |
References
Notes
Mirrored from https://github.com/sermikr0/CVE-2026-38427 on 2026-07-05.
| |