Tasmota fetch_jpg() Combined Buffer Overflow RCE Chain (CVE-2026-38422)
by Saidakbarxon Maxsudxonov (sermikr0) · 2026-07-05
- Severity
- Critical
- CVE
- CVE-2026-38422
- 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-38422 |
| 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, buffer-overflow, integer-overflow, rce, mjpeg, scripter |
| Related | CVE-2026-38426, CVE-2026-38427 |
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
Tasmota’s scripter driver (xdrv_10_scripter.ino) implements an MJPEG client via fetch_jpg() that contains two compounding memory-corruption bugs: a strcpy() overflow of a fixed 40-byte boundary[] buffer when parsing the Content-Type boundary string (CVE-2026-38426), and a uint16_t integer wraparound when parsing Content-Length for subsequent MJPEG frames that causes an undersized buffer allocation and stream desynchronization (CVE-2026-38427). Chained together in one attack session against a Tasmota device that connects to an attacker-controlled MJPEG server, the two primitives maximize heap corruption around adjacent WiFiClient/HTTPClient vtable pointers, significantly increasing the likelihood of remote code execution on the ESP32.
Vulnerability Details
Root Cause
fetch_jpg() copies an HTTP Content-Type boundary string into a fixed 40-byte stack/struct buffer with strcpy() (no bounds check), and separately parses Content-Length into a uint16_t via atoi(), silently truncating values above 65535 before allocating the receive buffer.
Attack Vector
- Stand up a malicious MJPEG HTTP server on an address the Tasmota device will be instructed to connect to (via a script using
fetchjp(), or MITM of an existing connection). - Phase 1: respond to the initial connection with an HTTP 200 whose
Content-Typeheader contains a boundary string longer than 39 characters, overflowingboundary[40]and corrupting adjacent struct fields includingWiFiClient/HTTPClientvtable pointers. - Phase 2: send subsequent MJPEG frame headers with
Content-Lengthvalues above 65535 (e.g. 65537), causinguint16_twraparound, an undersizedmalloc(), and stream/heap state corruption. - The combined corruption crashes the device deterministically and, depending on heap layout, can redirect execution via the corrupted vtable pointers.
Impact
Remote code execution or guaranteed crash/reboot loop 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-38422_poc.pyin this folder.
| |
The script runs a fake MJPEG HTTP server that first sends an oversized boundary string (phase 1 overflow) and then sends MJPEG frames with a Content-Length above 65535 (phase 2 wraparound), triggering combined heap corruption on a connecting Tasmota device.
Detection & Indicators of Compromise
Exception (28): epc1=... ...
Fatal exception ... rebooting
Signs of compromise:
- Unexpected reboots/crash loops on devices running scripts that call
fetchjp() - Outbound MJPEG connections to unrecognized or newly added external hosts
Remediation
| Action | Detail |
|---|---|
| Primary fix | Update to Tasmota v15.3.0.4 or later, which validates boundary length and Content-Length parsing in fetch_jpg() |
| 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-38422 on 2026-07-05.
| |