Abstract. CVE-2026-86876 is Apple’s CoreMedia out-of-bounds write: “a sandboxed process may be able to circumvent sandbox restrictions,” fixed “with improved bounds checking.”1 The candidate this note follows is CoreMedia’s metric event timeline, served to apps by mediaplaybackd. On iOS 26.6.2 (23G90) it has two independent bugs. FigMetricEventTimelineCreate allocates a prefix-sum table from the sum of client-supplied sizes and then writes it count times, a linear heap overflow whose qwords are fully chosen by the client. _met_addSubscriberForEventID turns a client EventID into a table index, checks only index < total with a signed compare, then loads subscribers[index] and, if that slot is NULL, stores a freshly created CFSet pointer there. iOS 26.7 (23H24) rejects non-positive counts and negative sizes, sizes the table from the count, and rejects negative and out-of-range indices. On a physical iPhone SE running 23G90, an ordinary development-signed app with no extra entitlements crashed mediaplaybackd three times at the out-of-range load, with fault addresses that match base + index × 8 exactly, and flipped the daemon’s subscriber state with a small negative index. On a research VM the same primitives produced a planted pointer in a sandbox-registration object, a use-after-free, and a type-confused CFSet call whose fault address was attacker bytes. Scope: protected files stayed EPERM in every run, no client-visible daemon address leak was found, and the type confusion did not reproduce on the physical phone. The bug class matches Apple’s text; the sandbox escape it describes was not reproduced.

1. Introduction

Apple credits Chris Bailey of Short Circuit.123 The 14 September pages list two other CoreMedia bugs next to this one: CVE-2026-64752 (crafted image, fixed by removing code, iOS 27 only) and CVE-2026-65344 (crafted video terminates an app, also an out-of-bounds write with bounds checking). The 23G90 → 23H24 CoreMedia diff therefore contains at least two out-of-bounds-write fixes, and the mapping in this note is a candidate until it is separated from CVE-2026-65344 (§10).

Layout: advisory (§2); binaries and the size diff (§3); the metric timeline service (§4); bug 1, the prefix table (§5); bug 2, the subscriber index (§6); physical iPhone results (§7); research VM results (§8); the sandbox question (§9); mapping caveats (§10); record and artifacts (§11).

Evidence labels used throughout.

  • Apple-confirmed — advisory text and page membership.
  • Patch-observed — ARM64 read on exact, hashed CoreMedia from both builds.
  • Lab-observed (SE) — physical iPhone SE 2020, iOS 26.6.2 / 23G90, ordinary signed app, no debugger.
  • Lab-observed (VM) — full-userspace 23G90 research VM, client run from a shell (unsandboxed), sometimes with Frida reading daemon memory. Never used as evidence of what a sandboxed app can do.
  • Hypothesis — untested inference.

2. Where Apple lists it

Advisory (14 Sep 2026) CVE-2026-86876
iOS 26.7 and iPadOS 26.7 present, CoreMedia1
iOS 27 and iPadOS 27 present, CoreMedia2
macOS Golden Gate 27 present, CoreMedia3
macOS Tahoe 26.7, Sequoia 15.8 present
visionOS 27, watchOS 27 present
tvOS 27 absent
Item Advisory text
Impact A sandboxed process may be able to circumvent sandbox restrictions
Description An out-of-bounds write issue was addressed with improved bounds checking

CISA-ADP: CWE-787, CVSS 3.1 5.2 (AV:L/AC:L/PR:L/UI:N/S:C/C:L/I:L/A:N).

3. Binaries and what changed

Side Cache UUID CoreMedia UUID SHA-256 Source ver.
iOS 26.6.2 / 23G90, iPhone17,3 IPSW F216D3F4-7064-3359-8840-41C1D1A2A72E C83ABE72-6B63-3C92-805A-5D69F55BE6A3 e80ab627287660628664d30b006f600cee7e3f53510e297551cc69d9a0625e0e 3330.13.2
iOS 26.7 / 23H24, iPhone17,3 OTA 5625EC35-B6D6-3C10-91B0-5B4C20FB77B7 B63D02BC-01BC-3F9A-8A83-90149364808B 4792ba2af559a4a4d67602728a4f03cfbefa6f32bd29068d20be460a0582ab08 3330.13.101.5

23G90 is inside Apple’s “before 26.7” range; Apple does not name it. The physical SE’s crash reports name the same CoreMedia UUID as the IPSW extract, and the research VM’s loaded __text matches the extract byte for byte (SHA-256 2247c998…6925).

Of the functions present on both sides, 28 changed size. The ones that grew by 8 bytes or more:

Symbol 23G90 23H24 Δ
_met_publishEventDispatch 0x334 0x3a8 +116
_hevcbridgeParseVDRRPUDataPayload 0xb9c 0xc08 +108
_met_subscribeByClassIDOnQueue 0x11c 0x164 +72
_met_addSubscriberForEventID 0xd8 0x108 +48
_FigMetricEventTimelineCreate 0x338 0x344 + cold stubs +12
_FigHEVCBridge_CreateDolbyRPUNAL 0x2f98 0x2fa0 +8

Four of the six are the metric timeline. The two HEVC/Dolby Vision RPU functions are a separate parser fix (§10). Every FigSandbox* function, _HandleSandboxRegistrationMessage, and _checkRequestAgainstSandboxRules is the same size on both sides: whatever Apple fixed, it was not the sandbox-check code itself.

4. The metric event timeline service

mediaplaybackd serves com.apple.coremedia.mediaplaybackd.figmetriceventtimeline.xpc. Apps reach it through CoreMedia’s client half (FigMetricEventTimelineCreateRemote, …RegisterSubscriber, …Publish), which wraps FigXPC messages. metserver_replyingMessageHandler (0x197de5704) dispatches on a four-character opcode:

Opcode Meaning Keys
cret create a timeline MaxNoOfClasses (count), EventCountByClassXPCArray (sizes)
sevi subscribe by EventID ObjectID, EventID (int64)
clsi subscribe a whole class ObjectID, ClassID
pubs publish an event ObjectID, event
disp dispose the timeline ObjectID

A timeline’s derived storage, as used by the code below:

Offset Field
+0x10 total — sum of all class sizes, number of subscriber slots
+0x18 count — number of classes (read only by the 23H24 code)
+0x28 prefix — int64[count], prefix sums of the sizes
+0x30 subscribers — CFSetRef[total]

An EventID is class << 56 | low56. Its slot is prefix[class] + low56. Everything in that formula — the sizes that build prefix, the class, and low56 — comes from the client.

5. Bug 1: the prefix table is sized by the sum and filled by the count

5.1 Vulnerable side, 23G90

cret copies the client’s int64 array into a count × 8 buffer (that part is correct) and calls FigMetricEventTimelineCreate(alloc, count, sizes, …) at 0x197de586c. Inside (x21 = count, x23 = sizes):

; sum the sizes — no sign check, no overflow check
0x197dcf77c  CMP   X21, #1
0x197dcf780  B.LT  zero_len
0x197dcf790  LDR   X11, [X9], #8
0x197dcf794  ADD   X8, X11, X8
0x197dcf798  SUBS  X10, X10, #1
0x197dcf79c  B.NE  0x197dcf790
0x197dcf7a0  LSL   X25, X8, #3                  ; request = sum * 8
0x197dcf7ac  BL    FigGetMallocZoneForMedia
0x197dcf7b0  MOV   X3, #0x10040436913F5         ; malloc type id
0x197dcf7c0  MOV   W1, #1
0x197dcf7c4  MOV   X2, X25
0x197dcf7c8  BL    malloc_type_zone_calloc
0x197dcf7cc  STR   X0, [X22,#0x28]              ; prefix table

; fill it — count iterations, not sum
0x197dcf7f4  MOV   X24, #0
0x197dcf7f8  LDR   X8, [X22,#0x28]
0x197dcf7fc  MOV   X9, X21
0x197dcf800  STR   X24, [X8], #8                ; write running sum, advance
0x197dcf804  LDR   X10, [X23], #8
0x197dcf808  ADD   X24, X10, X24
0x197dcf80c  SUBS  X9, X9, #1
0x197dcf810  B.NE  0x197dcf800

Whenever count > sum, the loop writes (count − sum) × 8 bytes past the allocation. The value written at step k is sizes[0] + … + sizes[k−1], so with negative sizes allowed every overflowing qword is an arbitrary int64 (choose sizes[k] = target[k+1] − target[k]).

Worked example from the first VM run: count = 0x1000, sizes = {1, 0, 0, …}. The sum is 1, the request is 8 bytes (16-byte slot), the loop writes 4096 qwords = 32768 bytes: 0 at offset 0, then 1 at offsets 8 through 32760. A debugger at the calloc return and loop end recorded x0 = 0x1020728d0, malloc_size = 16, final x8 = x0 + 0x8000, and the qword at +16 (a neighbor) changing from 0x15e8 to 1.

5.2 Fixed side, 23H24

0x197dfc738  CMP   X21, #0
0x197dfc73c  B.LE  cold.8                       ; count <= 0
0x197dfc740  CBZ   X23, cold.7                  ; no sizes array
0x197dfc784  LDR   X9, [...], #8
0x197dfc788  TBNZ  X9, #63, cold.6              ; any negative size
0x197dfc79c  LSL   X2, X21, #3                  ; request = count * 8
...
0x197dfc7e4  STR   X24, [X9, X8, LSL #3]        ; loop bound is count

Table and loop now agree on count, and negative sizes are gone, so a client can no longer pick the overflowing values.

6. Bug 2: a signed subscriber index with only an upper bound

6.1 Vulnerable side, 23G90

sevi looks up the timeline by ObjectID and calls vtable +0x10, _met_subscribeByEventID, which runs _met_addSubscriberForEventID (0x197dd05b4) on the timeline’s queue. X21 is the client’s EventID; X20 is the storage from §4:

0x197dd05ec  LDR   X8, [X20,#0x28]              ; prefix table
0x197dd05f0  ASR   X9, X21, #0x38               ; class, signed, unchecked
0x197dd05f4  LDR   X8, [X8,X9,LSL#3]            ; prefix[class]
0x197dd05f8  AND   X9, X21, #0xFFFFFFFFFFFFFF   ; low56
0x197dd05fc  ADD   X21, X8, X9                  ; index = prefix[class] + low56
0x197dd0600  LDR   X8, [X20,#0x10]              ; total
0x197dd0604  CMP   X21, X8
0x197dd0608  B.GE  error                        ; only index >= total is rejected
0x197dd060c  MOV   X19, X0
0x197dd0610  LDR   X8, [X20,#0x30]              ; subscribers
0x197dd0614  LDR   X0, [X8,X21,LSL#3]           ; read subscribers[index]
0x197dd0618  CBNZ  X0, add                      ; already a set → just add
0x197dd061c  BL    FigGetAllocatorForMedia
0x197dd062c  BL    CFSetCreate
0x197dd0630  LDR   X8, [X20,#0x30]
0x197dd0634  STR   X0, [X8,X21,LSL#3]           ; store new CFSet pointer
0x197dd0638  CBZ   X0, fail
add:
0x197dd063c  MOV   X1, X19
0x197dd0640  BL    CFSetAddValue                ; slot contents treated as a CFSet

A client gets a negative index in one message: create a timeline with sizes {−N, N+2} (sum 2, so prefix[1] = −N) and subscribe to EventID = 1 << 56. The index is −N, which is < total. Three things follow:

  • read: subscribers[−N] is loaded from anywhere below the array;
  • write: if it is NULL, a new CFSet pointer is stored there (value not chosen by the client, address chosen);
  • type confusion: if it is not NULL, whatever is there is passed to CFSetAddValue as a set.

Because the address is subscribers + (index << 3) modulo 2^64, an index near −2^61 wraps to a positive offset while still passing the signed < total check, so the slot can be above the array as well. And because class is never bounded, prefix[class] is itself an out-of-bounds read for classes outside [0, count).

The other subscribe path, _met_subscribeByClassIDOnQueue (clsi), walks a range of slots starting at prefix[class] with the same unchecked arithmetic, i.e. the same read/plant/add for a range of slots. _met_publishEventDispatch computes the same index to read a slot and dispatch to the set’s members.

6.2 Fixed side, 23H24

0x197dfd5f0  TBNZ  X21, #0x3F, error            ; reject EventID with bit 63
0x197dfd5f4  LSR   X8, X21, #0x38               ; class, now unsigned
0x197dfd5f8  LDR   X9, [X20,#0x18]              ; count
0x197dfd5fc  CMP   X8, X9
0x197dfd600  B.GE  error                        ; class < count
0x197dfd604  LDR   X9, [X20,#0x28]
0x197dfd608  LDR   X8, [X9,X8,LSL#3]
0x197dfd60c  AND   X9, X21, #0xFFFFFFFFFFFFFF
0x197dfd610  ADDS  X21, X8, X9
0x197dfd614  B.MI  error                        ; negative index
0x197dfd618  LDR   X8, [X20,#0x10]
0x197dfd61c  CMP   X21, X8
0x197dfd620  B.GE  error                        ; index < total
0x197dfd62c  LDR   X0, [X8,X21,LSL#3]

That is the +48 bytes. _met_subscribeByClassIDOnQueue (+72) and _met_publishEventDispatch (+116) gain the matching checks.

7. Physical iPhone SE, sandboxed app

7.1 Setup

iPhone SE 2020 (iPhone12,8), iOS 26.6.2 / 23G90. The probe app is an ordinary development-signed app with no custom entitlements. It checks the loaded CoreMedia UUID, creates a timeline through FigMetricEventTimelineCreateRemote, registers a callback, then sends raw sevi/pubs messages on the same connection so it can control EventID exactly.

One mistake cost a day and is worth stating: the first builds wrote EventID with xpc_dictionary_set_uint64, and CoreMedia reads it with xpc_dictionary_get_int64. The type mismatch reads as 0, so every early “send=0, no crash” run never exercised the index at all. Every result below uses set_int64 and reads the value back before sending.

Reachability was confirmed against the daemon, not inferred from return codes:

App input App sees mediaplaybackd logs ARM64 that produces it
cret, count 0 -19450 err=-19450 at <>:182 0x197de57f4 → error 0xFFFFB406, line 0xB6
sevi, valid object, index ≥ total -19452 err=-19452 at <>:231 addSubscriber cold.1
sevi, ObjectID high bit flipped -16152 << FigXPC >> err=-16152 at <>:6321 __figXPCServerLookupAndRetainAssociatedObject

7.2 Three crashes at the out-of-range load

Input: sizes {−0x40000000, 0x40000002}, EventID = 0x0100000000000000, so index = −0x40000000 (−8 GiB). Three fresh app processes, three daemon deaths:

.ips Daemon PID X8 (subscribers) X21 (index) X8 + X21×8 FAR
…-005023.ips 2802 0xd4b99c010 −0x40000000 0xb4b99c010 0xb4b99c010
…-005228.ips 3063 0x795388010 −0x40000000 0x595388010 0x595388010
…-005241.ips 3066 0x67d350010 −0x40000000 0x47d350010 0x47d350010

All three: EXC_BAD_ACCESS / SIGBUS / KERN_PROTECTION_FAILURE, CoreMedia UUID C83ABE72-…, runtime base 0x1a030b000 (slide 0x8630000), PC 0x1a0400614 = 0x197dd0614, the LDR in §6.1. Stack:

0  CoreMedia    met_addSubscriberForEventID + 96
1  CoreMedia    met_subscribeByEventIDOnQueue + 36
2  libdispatch  _dispatch_client_callout + 16
3  libdispatch  _dispatch_lane_barrier_sync_invoke_and_complete + 56
4  CoreMedia    met_subscribeByEventID + 100
5  CoreMedia    metserver_replyingMessageHandler + 788
6  CoreMedia    figXPC_HandleMessage + 2024
7  libxpc       _xpc_connection_call_event_handler + 112

The heap base moves with each restart; the instruction, index, and arithmetic do not. These faults are the read at 0x…614. The STR four instructions later never ran in these three.

7.3 A small negative index changes daemon state

With sizes {−3, 5} and the same class, the index is −3: a mapped slot 24 bytes below the array. The app publishes the event before and after sevi and counts callbacks:

neg-oracle: create=0 register=0 subscribe=0
  prepub=0 precb=0       slot read as NULL → no subscribers → no callback
  send1=0                sevi plants a CFSet at subscribers[-N]
  publish=0 callbacks=1  publish finds the planted set → callback delivered

Same result in three new app processes and a fourth same-process repeat; a normal input’s direct publish gives the positive control of 1. Where the slot held malloc metadata instead of NULL (index −1), the daemon accepted the sevi and then died in the next publish (objc_msgSend ← met_publishEventDispatch, KERN_INVALID_ADDRESS at 0x0040000000000010), twice. So from inside the sandbox the app has a three-way probe of any slot near the array: NULL (silent), a set it planted (callback), or garbage (daemon crash).

7.4 The prefix overflow from the app

cret with sizes {−1000000, 1000002, −102, 102} and count 4 (sum 2, two qwords of overflow) returned 0 on the phone in some runs and -16155 in others. After a successful one, sevi on every timeline, including a control created afterward, returned -19452, while new cret still worked. That is consistent with the overflow corrupting neighboring prefix tables (§8.3), but on the phone there was no way to read them, so it stays an observation, not a mechanism.

clsi from the app returned -16155; from the VM shell it returned 0. The same code also shows up on the VM in states that have nothing to do with policy, so whether clsi is gated for sandboxed clients is unresolved.

8. Research VM: what the primitives can do with addresses known

The VM is iPhone17,3 / 23G90 with full userspace. The client is a CLI started over SSH, not sandboxed. Where addresses appear, Frida read them from the daemon; the client had no way to learn them.

8.1 A planted pointer in a sandbox-registration object

cre8 creates a sandbox registration: FigSandboxRegistrationCreate stores the retained ExtensionPath at +0x10, calls sandbox_extension_consume on the token bytes, and stores the handle at +0x20. With the registration at 0x69d2c0540 and the subscriber array at 0x69d420000, EventID = 0x010000fffffd40aa aimed the STR at registration+0x10. Before: 0. After: 0x69d434090, the new CFSet. The registration and the array live in different zones (DefaultMallocZone vs. CMMediaZone) 10.6 MB apart; the signed index crosses that. The offset between them was −431472 and −417148 slots in two later daemon instances, so it is not a constant an attacker could hard-code.

8.2 Use-after-free into type confusion, no addresses needed

Subscriber arrays of two timelines created back to back sit two slots apart in their type pool. That gives a constant index without any leak:

T1 sizes {1,1}     victim,   T1.subscribers = X
T2 sizes {-2,4}    attacker, T2.subscribers = X + 16, prefix[1] = -2

1. sevi on T2, class 1, low56 0   → index -2: CFSet into T1.subscribers[0]
2. publish                        → callback 1 (plant confirmed)
3. disp T1                        → finalizer CFReleases each slot: set freed
4. 200 × cre8                     → DefaultMallocZone spray, chosen path bytes
5. sevi on T2 again               → CFSetAddValue on the freed, reclaimed slot

The daemon died in __CF_IS_OBJC ← CFSetSetValue ← met_addSubscriberForEventID with KERN_INVALID_ADDRESS at 0x656c7070415e6e6f and “possible pointer authentication failure.” Read little-endian, those bytes are on^Apple: part of the path string sprayed in step 4. The daemon dereferenced attacker bytes as an object’s isa.

The same sequence from the sandboxed app on the physical SE planted (callback 1), disposed, sprayed, and ran the second sevi without a crash: post_cb=1, i.e. the freed slot had not been reclaimed by the spray. The likely reason is that production xzone malloc keeps type-segregated pools, so a CFData/CFString allocation does not land on a freed CFSet; that is an inference from the outcome, not a measured layout.

8.3 Prefix overflow onto a neighboring timeline

Prefix tables of small timelines are 16-byte neighbors in their own pool, and freed slots are reused LIFO. With Frida reading the tables:

create T_B {1,1}, T_C {1,1}       T_C.prefix = {0, 1}
disp T_B                          T_B's 16-byte slot freed
create T_E {-1000000, 1000002, -102, 102}, count 4, sum 2
                                  T_E reuses T_B's slot; qwords 2-3 overflow
                                  T_C.prefix = {2, -100}

After that, sevi and publish on T_C use an index the attacker wrote. This removes the need for negative sizes on the victim and is the reason the 23H24 create-side checks matter.

8.4 Limits found on the VM

  • No overflow into pointers from bug 1. The sizes copy buffer, the prefix table, the timeline object, and the subscriber array are four different typed allocations in four different regions. A linear prefix overflow stays among prefix tables (integers).
  • Client-side self-kill. FigMetricEventTimelineCreateRemote builds a local mirror timeline with the same buggy loop, so a count > sum create through the framework overflows the client’s heap first (PAC_EXCEPTION in mfm_alloc). Attacks have to send raw cret.
  • No leak in the replies. Full dumps of sevi/pubs/clsi/stae replies contain only .ErrorReturn and .Token (the daemon PID). ObjectIDs are (pid << 48) | (server_number << 40) | counter | type with no heap bits. CFCopyDescription of a timeline prints %p, but only a debugger called it.
  • Value not chosen. The write in bug 2 stores a CFSet pointer; it cannot write an arbitrary value.

9. The sandbox question

Apple’s impact sentence is about circumventing the sandbox. Every authorization oracle tried on the physical SE stayed closed:

  • open of /private/var/mobile/Media and /usr/libexec/mediaplaybackd: EPERM before and after the negative-index state change, in the same process; the kernel kept logging file-read-data denies.
  • FigShared_CopyDiskCacheParams on a protected directory: returns 0 to the app, but the kernel denied the app’s file-issue-extension and the daemon’s file-write-create of diskcacherepository.plist both before and after. A 0 from that API is not an authorization signal; the client path continues after -17507.
  • sandbox_check queries agreed: no path tested was “app denied, daemon allowed” for writing.

What is established is the step before an escape: a sandboxed app can make a privileged daemon read and write out of bounds, and on a research VM the write can corrupt a sandbox-registration object and the resulting use-after-free gives attacker bytes as an object pointer. What is missing is a client-visible leak to aim the write on a real device, a reclaim that works under production malloc, and any protected resource actually becoming accessible.

10. Mapping caveats

  • The same update fixes CVE-2026-65344 (crafted video, out-of-bounds write). The HEVC/Dolby Vision RPU parser changes (_hevcbridgeParseVDRRPUDataPayload +108 adds a pre-write upper bound) match that video wording; the metric changes match the sandbox wording. That split is a reading of the advisory, not something Apple published.
  • The metric fixes cover every path that computes the index (create, sevi, clsi, publish), which is what a deliberate fix for this bug class looks like. It does not prove Apple’s report used the same route.
  • 23H24 has not been run with the same app. The fixed-side behavior in §5.2/§6.2 is from ARM64 only.

11. Record and artifacts

Item Result Label
Bug 1 prefix table sum×8, filled count times; client-chosen qwords Patch-observed
Bug 2 signed index, upper bound only; OOB read, conditional pointer write, type confusion Patch-observed
Fix count/size checks, count×8 table; bit 63, class, ADDS/B.MI, upper bound Patch-observed
Sandboxed app → daemon three SIGBUS at 0x197dd0614, FAR = base + index×8 Lab-observed (SE)
Sandboxed app state change callbacks 0 → 1 after negative-index sevi Lab-observed (SE)
Pointer planted in registration +0x10: 0 → CFSet, debugger-supplied addresses Lab-observed (VM)
UAF → type confusion fault at 0x656c7070415e6e6f (on^Apple) Lab-observed (VM); not on SE
Protected access, leak, code execution, 23H24 replay not shown —
Artifact SHA-256
mediaplaybackd-2026-09-29-005023.ips 44f7634c6557e3fb9d31fa9bde6ad7c6fc79586201ac7f49a03f54fce3b31d3f
mediaplaybackd-2026-09-29-005228.ips bb4ce48b3d59a2524a9b6f7b14f47c661a5a8d5b6838aa18aa9fee76ddadc34f
mediaplaybackd-2026-09-29-005241.ips f356955e1a7a86b72d1103b6c3f5e132f044bbc89f7f8bd69e46d163ea1a53fc
Normalized crash fingerprint (all three) 707b713a6a9924d09854365f55a3f7eaafe0b1c8ac314649fdc6b8c7bc330981
Probe app executable (far-negative build) eb28a38e3bee2ab6a8a1de563498afc013843dfc715e43bd5b6013d847eb5939
Probe app executable (count-0 control) 54f9b6146a642f92116e40f13859d8d0c3917861aaa8ea40c1a786de4c7f2fbb
23G90 CoreMedia e80ab627287660628664d30b006f600cee7e3f53510e297551cc69d9a0625e0e
23H24 CoreMedia 4792ba2af559a4a4d67602728a4f03cfbefa6f32bd29068d20be460a0582ab08

[1] Apple, “About the security content of iOS 26.7 and iPadOS 26.7,” 14 September 2026. https://support.apple.com/en-us/149041

[2] Apple, “About the security content of iOS 27 and iPadOS 27,” 14 September 2026. https://support.apple.com/en-us/149034

[3] Apple, “About the security content of macOS Golden Gate 27,” 14 September 2026. The same CoreMedia entry is on the Tahoe 26.7, Sequoia 15.8, visionOS 27, and watchOS 27 pages. https://support.apple.com/en-us/149035

End of noteBack to the archive