
CVE-2026-20687: AppleJPEGDriver startDecoder Timeout UAF — iOS/macOS kernel vulnerability leading to deferred panic (A19 Pro, iOS 26.3 RC)
CVE-2026-20687 · Enfilade · enfilade.io
Component: Kernel
Impact: An app may be able to cause unexpected system termination or write kernel memory.
Description: A use after free issue was addressed with improved memory management.
| iOS | 26.3 (23D125) (tested) |
| macOS | — |
| Component | AppleJPEGDriver |
| Patched | iOS 26.4 / iPadOS 26.4 |
| Hardware | iPhone18,2 (iPhone 17 Pro Max, A19 Pro) |
Running the PoC will kernel-panic the device. Save your work before running. Repeated panics may cause filesystem corruption. For security research purposes only.
The timeout path in startDecoder_sync frees a request but leaves its embedded queue-node pointer in the per-codec vector. A later queue walk dereferences the stale node and the kernel panics under MTE tag-check enforcement. The panic is typically deferred until a subsequent synchronous JPEG decode runs — on iPhone this reliably occurs when the Camera app is opened.
// Primes the driver; the panic is usually deferred until Camera is opened.
IOServiceOpen("AppleJPEGDriver");
for (int i = 0; i < N; i++) {
startDecoder_async(); // queue_io_gated: vector.push(req + 0x78)
}
IOServiceClose(conn);
// Later, opening Camera triggers:
startDecoder_sync();
queue_io_gated: vector.push(req + 0x78);
wait(10s) -> TIMEOUT;
pool_free(req); // BUG: does NOT dequeue (req + 0x78)
// Later still (finish_io_gated):
fullSpeedRequestExist():
node_ptr = vector[i]; // stale: node_ptr == (freed req + 0x78)
req2 = *(node_ptr + 0x8); // UAF read -> MTE tag fault -> panic
ios-app/Test.xcodeproj in Xcode.See LICENSE.