Executive Summary
A critical-severity vulnerability has been identified in schreibfaul1/ESP32-audioI2S version 3.4.5, a widely used Arduino-compatible audio decoding library for the ESP32 microcontroller family. The flaw is an unsigned integer overflow in the library's internal buffer size calculation logic. When triggered, the overflow causes the library to allocate a PSRAM audio buffer that is significantly smaller than required. Subsequent normal audio buffer read and write operations then access memory beyond the end of this undersized allocation, resulting in a heap buffer overflow.
This vulnerability affects any embedded device — including IoT audio streamers, smart speakers, intercom systems, and media players — running the ESP32-audioI2S library at or below version 3.4.5. Exploitation can lead to arbitrary code execution, denial of service, or memory corruption depending on the specific heap layout at runtime.
Vulnerability Overview
| Field | Details |
|---|---|
| CVE ID | CVE-2026-51259 |
| CVSS v3.1 Score | 9.8 (Critical) |
| CVSS Vector | AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
| CWE | CWE-190 (Integer Overflow), CWE-122 (Heap-Based Buffer Overflow) |
| Affected Software | schreibfaul1 ESP32-audioI2S 3.4.5 and earlier |
| Affected Platforms | ESP32, ESP32-S3, ESP32-P4 (any variant with PSRAM) |
| Patch Available | Monitor upstream repository for fix |
| Published | 2026-07-29 |
| Source | NVD / NIST |
Technical Details
Integer Overflow in Buffer Size Calculation
The ESP32-audioI2S library allocates a large PSRAM-backed audio buffer at initialization time, sized based on calculated parameters derived from stream or configuration data. The vulnerability exists in the buffer size arithmetic, where intermediate unsigned integer values can wrap around to zero or a very small number when the operands exceed the maximum value of the unsigned type.
A simplified illustration of the flawed pattern:
// Vulnerable pattern (illustrative)
uint16_t channels = stream_channels; // e.g. 2
uint16_t sampleSize = bytes_per_sample; // e.g. 4
uint16_t blockSize = desired_frames; // e.g. 16384
// All operands are uint16_t — multiplication overflows at 65535
uint16_t bufferSize = channels * sampleSize * blockSize;
// With the values above: 2 * 4 * 16384 = 131072 > 65535
// Result wraps to: 131072 % 65536 = 536 (tiny!)
// PSRAM allocation uses the wrapped (undersized) value
uint8_t* audioBuf = (uint8_t*)ps_malloc(bufferSize);Because all intermediate calculations are performed in a narrow unsigned type (e.g., uint16_t or uint32_t in constrained paths), the product silently wraps. The resulting bufferSize value passed to ps_malloc() is a small fraction of what the audio pipeline actually needs.
Undersized PSRAM Buffer Allocation
PSRAM (ps_malloc) allocates exactly the wrapped (erroneous) byte count. No runtime assertion or return-value check catches the discrepancy between the allocated size and the expected size because the library propagates the wrapped value consistently — the allocated size matches the (incorrect) computed size, so basic sanity checks pass.
The audio buffer is then treated throughout the pipeline as if it were the full, correctly sized buffer. Pointers into the buffer are calculated using the correct (non-overflowed) offsets, meaning they immediately reference memory outside the allocated region.
Out-of-Bounds Read and Write
Once the undersized buffer is in use, normal library operations trigger the overflow condition:
// Later, audio pipeline writes using correct (large) offsets
// into the undersized PSRAM buffer:
audioBuf[correctOffset] = decodedSample;
// correctOffset >> allocatedSize --> heap OOB writeBecause PSRAM is part of the device's heap address space, out-of-bounds writes corrupt adjacent heap allocations. Depending on what follows the audio buffer in the heap, this can overwrite heap metadata, FreeRTOS task control blocks, network stack buffers, or other application data.
Attack Scenario
- Attacker delivers a crafted audio stream to a device running ESP32-audioI2S (e.g., an internet radio application, a networked media player, or a voice assistant device).
- The stream is designed (or the device's configuration leads) to select parameter combinations that trigger the integer overflow in the buffer size calculation.
- The library initializes with a PSRAM buffer too small for actual audio throughput.
- As the device decodes and plays back the audio stream, every normal write into the buffer overflows into adjacent heap memory.
- The attacker's controlled input data fills the overflowed region, potentially overwriting adjacent objects — enabling arbitrary code execution or a reliable crash (DoS).
Network-accessible devices are at greatest risk since an attacker can trigger this condition remotely by serving a crafted audio stream with no authentication required (CVSS AV:N, PR:N, UI:N).
Impact on Embedded IoT Devices
ESP32-audioI2S is one of the most popular audio libraries in the Arduino/ESP32 ecosystem, with broad adoption across consumer and hobbyist IoT devices. The embedded nature of these targets amplifies the impact:
- No ASLR: ESP32 firmware typically lacks address-space layout randomization, making heap layout predictable and overflow exploitation more reliable.
- No OS memory protection: FreeRTOS does not enforce process isolation or memory protection between tasks by default.
- Persistent impact: A compromised device has no user-visible indication and may remain under attacker control indefinitely.
- Physical access implications: Compromised audio devices may have microphones, network access, or control interfaces that attackers can leverage post-exploitation.
- Supply chain reach: Library-level vulnerabilities propagate to all products built on the affected version, including commercial products that may not apply patches promptly.
Remediation
Immediate Actions
| Priority | Action |
|---|---|
| High | Monitor the schreibfaul1/ESP32-audioI2S GitHub repository for a patched release |
| High | Restrict network access to affected devices where possible |
| Medium | Audit audio input sources — prefer trusted, controlled streams over arbitrary internet radio |
| Medium | Apply firmware-level heap canaries or stack guards if your toolchain supports them |
Workaround (Until Patch Available)
If you must continue operating affected devices, consider adding a compile-time or runtime guard on the calculated buffer size:
// Defensive workaround — validate buffer size before allocation
size_t bufferSize = (size_t)channels * (size_t)sampleSize * (size_t)blockSize;
// Sanity check: reject unrealistically small sizes
if (bufferSize < MINIMUM_EXPECTED_BUFFER_SIZE) {
log_e("Buffer size calculation overflow detected — aborting init");
return false;
}
uint8_t* audioBuf = (uint8_t*)ps_malloc(bufferSize);The key fix is to cast operands to a wider type (size_t or uint32_t) before multiplication, preventing the intermediate overflow. The upstream maintainer should apply this fix in the affected buffer size calculation code path.
When a Patch Is Released
- Update the library to the patched version via Arduino Library Manager or by pulling the latest tag from GitHub.
- Rebuild and reflash all affected firmware images.
- Verify the update by confirming the library version string in your sketch.