How I Discovered CVE-2026-43681: An AppleRAID Kernel Heap Overflow in macOS
August 3, 2026 · David Ige

Acknowledgement
First and foremost, I give all glory to God. Every insight, every moment of clarity, and the patience to keep testing this issue came from Him.
Publication status: Publicly disclosed. Apple fixed CVE-2026-43681 in macOS Sonoma 14.8.8, macOS Sequoia 15.7.8, and macOS Tahoe 26.6, released July 27, 2026.
At a Glance
| CVE | CVE-2026-43681 |
| Affected component | com.apple.driver.AppleRAID |
| Root cause | An on-disk member index was used before checking it against the allocated member count |
| Directly demonstrated impact | Kernel out-of-bounds access, an eight-byte pointer write beyond a heap allocation, and reproducible kernel panics |
| Apple's published impact | A local user may be able to read kernel memory |
| Validated environment | macOS 26.4, build 25E5233c, arm64 |
| Fixed releases | macOS Sonoma 14.8.8, macOS Sequoia 15.7.8, and macOS Tahoe 26.6 |
| Fix description | A buffer overflow was addressed with improved bounds checking |
Introduction
In March 2026, I found a kernel memory-safety vulnerability in Apple's software RAID driver. The bug lived in AppleRAIDSet::addMember(), where metadata read from a disk supplied an index into a kernel heap array.
The array held pointers to the members of a RAID set. Its capacity was derived from the number of members declared in the same on-disk metadata. The problem was simple and dangerous: AppleRAID checked whether the set had room for another active member, but it did not verify that the supplied member index was inside the allocated array.
That left two attacker-influenced values with different jobs:
memberCountdetermined the size of themembers[]heap allocation; andmemberIndexdetermined which eight-byte slot AppleRAID accessed.
When memberIndex exceeded memberCount, the driver loaded from and could store to memory beyond members[]. A crafted RAID header therefore turned disk metadata into a kernel heap out-of-bounds access during device discovery.
I confirmed the vulnerable path on a real Mac, directly observed the write in the live kernel, reproduced panics across multiple allocation sizes, and later verified that a post-fix AppleRAID binary rejected the malformed member instead of crossing the allocation boundary.
How I Got Here
Why AppleRAID stood out
Kernel parsers for storage metadata sit on a particularly important trust boundary. Their inputs may arrive from removable media, virtual disk images, or damaged filesystems, but the parsing work occurs with kernel privilege.
AppleRAID implements macOS software RAID and understands metadata embedded in Apple_RAID partitions. When such media appears, IOKit can match the partition, load the driver, and pass the on-disk configuration into AppleRAID's object model. No network service or high-level application parser sits between the bytes on disk and the kernel code interpreting them.
I began by mapping that path from the RAID header parser into set creation. The interesting sequence was:
disk or disk image appears
|
v
AppleRAIDMember::readRAIDHeader()
|
v
AppleRAIDMember::parseRAIDHeaderV2()
parses the on-disk configuration
|
v
AppleRAID::newMember()
|
v
AppleRAIDSet::initWithHeader()
allocates members[memberCount]
|
v
AppleRAIDSet::addMember()
accesses members[memberIndex]
The question became whether all of the counts and indexes crossing that path were checked against the allocation they eventually addressed.
The static lead
In the vulnerable build, resizeSet() allocated space for memberCount pointers. At eight bytes per pointer, the allocation size was effectively:
members = kalloc(memberCount * sizeof(void *));The reconstructed shape of addMember() was:
uint32_t index = member->memberIndex; // from the RAID header
if (activeMemberCount >= memberCount) {
return false;
}
if (members[index] != NULL) { // out-of-bounds load
return false;
}
members[index] = member; // out-of-bounds store
return true;This is simplified pseudocode reconstructed from the binary; it is not Apple source. The important distinction is between the check that existed and the check that was missing. Limiting activeMemberCount does not make an arbitrary memberIndex safe. The code also needed to establish:
memberIndex < memberCountbefore either array access.
Turning the lead into runtime evidence
I built controlled disk images containing valid enough GPT and AppleRAID structures to reach the real driver, then changed only the relationship between the declared member count and member index.
The in-range control followed the normal path. The out-of-range variant caused the kernel allocator to detect corruption outside the members[] allocation. The failure reproduced across reboots and across different typed-allocation size classes.
The panic signature frequently took this form:
[kalloc.type.var...]: element modified after free
off: <controlled boundary-relative offset>
val: <AppleRAIDMember kernel pointer>
last started kext: com.apple.driver.AppleRAID
That was strong evidence, but I wanted to distinguish an actual out-of-bounds store from a misleading downstream crash. I therefore observed the relevant slot immediately before and after AppleRAIDSet::addMember() on the live kernel:
before: members[index] = 0x0000000000000000
after: members[index] = <AppleRAIDMember kernel pointer>
The target slot was beyond the allocation boundary. The eight-byte pointer write was real.
The Vulnerable Data Flow
The V2 AppleRAID header stored its configuration as an XML property list. Two fields eventually defined the unsafe relationship:
AppleRAID-Members
-> array length becomes memberCount
-> memberCount * 8 bytes allocated for members[]
AppleRAID-MemberIndex
-> parsed as a 32-bit index
-> shifted by 3 for an eight-byte pointer slot
-> used in members[memberIndex]
The resulting address calculation was conceptually:
target = members_base + (memberIndex * 8)
For an in-range member, that points into the array. For an out-of-range member, the same calculation points into some other kernel heap state.
Before performing the store, addMember() loaded the target slot to determine whether it was already occupied. The vulnerable sequence therefore included both an out-of-bounds load and a possible out-of-bounds store:
ldr x_check, [x_members, x_index, lsl #3]
cbnz x_check, duplicate_member
str x_member, [x_members, x_index, lsl #3]This is normalized AArch64-style pseudocode for readability. The exact register assignment varied with the build, but the missing bounds invariant did not.
Why the Existing Check Was Insufficient
The existing count check answered this question:
Is the set already holding as many active members as it declared?
It did not answer the question needed for memory safety:
Is this particular index inside the allocated member-pointer array?
Those properties are independent. A set can have zero or one active members while a new member still claims an index far beyond the end of a two-element array.
This is a recurring parser lesson: validating the number of objects processed does not automatically validate every attacker-provided identifier used as an array index.
End-to-End Validation
I validated the issue on a real arm64 Mac running macOS 26.4 build 25E5233c. The driver version was AppleRAID 5.1.0.
The evidence progressed in stages:
- A safe control reached AppleRAID without crossing the array boundary.
- A malformed member index produced reproducible kernel panics.
- Different declared member counts moved the vulnerable allocation through 16-byte, 256-byte, and later 1024-byte typed-kalloc size classes.
- Live tracing showed a zero value before
addMember()and anAppleRAIDMemberpointer afterward at an address beyond the allocation. - In a groomed run, the planted pointer remained observable for more than 31 minutes while the adjacent allocation stayed live.
The index calculation was visible in crash-state registers as well:
x11 = <memberIndex from disk>
x10 = memberIndex << 3
That established control of the array offset. It did not establish control of the heap base address or the value written. The stored value remained a valid kernel pointer to the newly created AppleRAIDMember object.
Security Impact
The trust boundary made the bug significant. An attacker-controlled index stored in AppleRAID metadata was used as a kernel heap array subscript during RAID member discovery, resulting in an out-of-bounds kernel memory access.
A local user could exploit the flaw by causing macOS to process crafted AppleRAID media, such as a disk image or removable storage device, to read or corrupt kernel memory and crash the system. The issue therefore affected both confidentiality and system stability.
The vulnerability was fixed across the Sonoma, Sequoia, and Tahoe release lines.
What Apple Fixed
Apple released the fixes on July 27, 2026. Its macOS Tahoe 26.6 security page states:
AppleRAID
Impact: A local user may be able to read kernel memory
Description: A buffer overflow was addressed with improved bounds checking.
CVE-2026-43681: impost0r (ret2plt), David Ige - Beryllium Security
I also tested a later AppleRAID binary from macOS 27.0 build 26A5368g. The same out-of-range member that reached the vulnerable access on macOS 26.4 was rejected, the device detached cleanly, and the Mac remained on the same boot. Static comparison showed new member-index guards in the add and remove paths.
That is the correct fix at this boundary: reject the malformed index before the first array load or store.
How This Class of Bug Should Be Prevented
On-disk metadata must remain untrusted even when it describes a familiar Apple storage format. A robust parser should:
- validate every index against the capacity of the specific array it addresses;
- perform the validation before both reads and writes;
- reject inconsistent relationships between member arrays, member counts, and per-member indexes;
- use checked arithmetic when turning counts into allocation sizes or byte offsets;
- keep parsing and object publication separate until all structural invariants hold; and
- test malformed metadata at the exact boundary, one element below it, and one element beyond it.
The key invariant in this case was small enough to write in one line:
if (memberIndex >= memberCount) {
return false;
}Its placement was the difference between rejecting a malformed RAID member and addressing memory outside a kernel heap allocation.
Disclosure Timeline
- March 2026: The AppleRAID member-index vulnerability was discovered, validated on macOS, and reported to Apple.
- March 2026: Additional live-kernel tracing confirmed the out-of-bounds pointer write and explored its stability and limits.
- July 27, 2026: Apple released macOS Sonoma 14.8.8, macOS Sequoia 15.7.8, and macOS Tahoe 26.6 with the fix and published CVE-2026-43681.
- August 2026: This technical disclosure was prepared.