CVE-2026-86950: Apple CoreGraphics Glyph Zero-Day Exploited in Targeted Spyware Attacks

·

On September 28, 2026 Apple shipped emergency updates for an out-of-bounds write in CoreGraphics, the low-level 2D rendering framework behind every glyph, PDF and image Apple devices draw. Tracked as CVE-2026-86950 (CVSS 3.1 base 8.8, CWE-787), the bug was reported by Meta's product security team and, in Apple's words, "may have been exploited in an extremely sophisticated attack against specific targeted individuals." CISA added it to the Known Exploited Vulnerabilities catalog on September 29 with a federal remediation deadline of October 2.

The root cause is not a classic bounds-check miss. It is a compiler optimization differential: two code paths that convert the same floating-point glyph coordinate to fixed-point produce different results when the value overflows a 32-bit integer. That inconsistency corrupts a glyph's bounding box, undersizes the rasterizer's coverage buffer, and lets a crafted font write past the allocation while drawing a single letter.

A public proof-of-concept now exists — it reliably crashes unpatched iPhones and Macs with a booby-trapped PDF, though weaponizing it to code execution is separate work. This brief walks the full glyph rendering path from CGContextShowGlyphsAtPositions to the overflow, maps the mercenary-spyware pattern it fits, and gives patch-posture hunts you can run today.

◈ Table of Contents

01 Vulnerability Profile 02 Disclosure & Exploitation Timeline 03 Affected Products & Versions 04 Delivery Vector 05 Technical Deep Dive 06 The Rendering Attack Chain 07 From Crash to Code Execution 08 The Mercenary-Spyware Pattern 09 Indicators & Hunt Signals 10 Detection & Fleet Queries 11 MITRE ATT&CK Mapping 12 Mitigation & Hardening 13 Sources & References
🎯

Vulnerability Profile

PHASE 01

CVE-2026-86950 is a memory-corruption flaw in a component that runs on virtually every Apple device — and one that processes attacker-supplied data (fonts, PDFs, images) constantly. That combination is exactly what mercenary spyware vendors shop for: a bug in a universally reachable parser that an attacker can trigger with a file the victim never has to open deliberately.

AttributeDetail
CVE IDCVE-2026-86950
ComponentCoreGraphics (anti-aliased path rasterizer)
ClassCWE-787 — Out-of-bounds Write HIGH
CVSS 3.18.8 — AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
ReporterMeta Product Security
Public analysisCalif — "The Great Glyph Grift" + PoC harness
Exploited in wildYes — Apple-confirmed targeted attacks; CISA KEV
Published (NVD)September 28, 2026
CISA KEV addedSeptember 29, 2026 (action due Oct 2, 2026)
Patched iniOS/iPadOS 26.7.1 · macOS Tahoe 26.7.1 · macOS Sequoia 15.8.1

The CVSS user-interaction flag (UI:R) understates the real risk. In the targeted attacks Apple describes, "interaction" can be as little as receiving a message that auto-renders a preview — the user never knowingly opens anything. Treat this as a near-zero-click bug when prioritizing.

🕐

Disclosure & Exploitation Timeline

PHASE 02
T
How the disclosure unfolded
Timeline
  • 1
    Pre-disclosure (date undisclosed) — Attacks observed in the wild against specific individuals on iOS versions prior to iOS 27. Meta's product security team identifies the underlying CoreGraphics flaw and reports it to Apple.
  • 2
    Sep 28, 2026 — Apple releases iOS/iPadOS 26.7.1, macOS Tahoe 26.7.1 and macOS Sequoia 15.8.1, crediting the fix and acknowledging possible exploitation in "an extremely sophisticated attack." NVD publishes CVE-2026-86950.
  • 3
    Sep 29, 2026 — CISA adds CVE-2026-86950 to the Known Exploited Vulnerabilities catalog, setting a federal remediation deadline of October 2.
  • 4
    Oct 1, 2026 — Calif publishes "The Great Glyph Grift," a full root-cause writeup, plus a public PoC harness that generates a crashing PDF/font pair. Reporting notes Meta quietly hardened WhatsApp's PDF attachment validation around the same window.
  • 5
    Oct 1, 2026 onward — SANS ISC and multiple outlets flag the PoC and the possible WhatsApp delivery path, raising the odds of copycat crash and exploit-development activity.
📦

Affected Products & Versions

PHASE 03

Because CoreGraphics is shared system-wide, the surface is every app that renders a glyph, PDF or image — Mail, Messages, Safari preview, QuickLook, and third-party apps that use the system text stack. Note the split macOS fix line: Tahoe (26.x) and the still-supported Sequoia (15.x) each get a patch; the next major releases were unaffected.

PlatformVulnerableFixed buildStatus
iOS / iPadOS< 26.7.1 (iOS before iOS 27 targeted)26.7.1PATCH NOW
macOS Tahoe26.0 – 26.7.026.7.1PATCH NOW
macOS Sequoia< 15.8.115.8.1PATCH NOW
iOS 27 / macOS 27Not affected—CLEAR

Don't let "iOS before iOS 27" lull you. The enterprise reality is a long tail of devices parked on 26.x and 15.x for app-compatibility reasons. Those are exactly the fleet members an operator wants — fully functional, in active use, and unpatched. Inventory by build, not by marketing version.

📨

Delivery Vector

PHASE 04

Apple did not publish the delivery method, but the component gives strong hints and the public analysis narrows it further. CoreGraphics renders content the moment an app decides to preview it — which is why messaging apps, mail, and web previews are the classic routes for this bug class.

D1
Booby-trapped PDF with a crafted embedded font
Primary

The PoC ships a minimal PDF that embeds a crafted TrueType font. When CoreGraphics rasterizes a glyph from that font, the overflow fires. A PDF is an ideal carrier: it travels as an innocuous attachment and is auto-previewed by many apps without an explicit "open."

D2
The WhatsApp signal
Corroborating

Around the patch window, Meta quietly tightened WhatsApp's attachment-scoring to flag malformed or unverifiable embedded fonts in PDFs. That is a strong tell that a font-in-PDF was a real delivery path, though no source confirms WhatsApp was the exploited channel for this specific CVE.

🔗
SecurityWeek — Apple patches Meta-reported zero-day
Primary reporting on reporter, targeting and patch set
OPEN ↗
💬

Messaging Preview

Chat apps that render document thumbnails or inline PDF previews reach CoreGraphics before any tap.

✉️

Mail & QuickLook

Mail attachment previews and Finder QuickLook both invoke the system render path for PDFs and fonts.

🌐

Web / Safari

Web content embedding a crafted font or PDF is drawn through the same rasterizer stack.

🔬

Technical Deep Dive

PHASE 05

This is the part that makes CVE-2026-86950 interesting. The bug is not a missing check — it is two correct-looking conversions that disagree only at the integer boundary, and that disagreement is enough to poison every size calculation that follows. The analysis below follows Calif's published root cause.

1
The conversion function
Root cause

CoreGraphics' anti-aliased rasterizer uses a 4096×4096 sub-pixel box model. Floating-point coordinates become fixed-point through an inline helper that scales by 4096 and rounds:

// pre-patch aa_double_to_fixed()
static inline int32_t aa_double_to_fixed(double px) { double v = 0.5 + 4096.0 * px; return (int32_t)v; // unchecked narrowing cast }

On its own this looks fine. The problem is what the compiler emits for that (int32_t)v cast in different surrounding code — and whether v can be pushed outside the int32 range (±2,147,483,647) by a hostile glyph.

2
The compiler optimization differential
The twist

When the scaled double exceeds int32 bounds, the narrowing cast is undefined behavior — and the compiler is free to lower it differently in different functions. On ARM64 the two call sites diverge:

Call siteEmitted instructionOut-of-range result
aa_movetoFCVTZS Wd, DnSaturates to INT32_MAX / INT32_MIN
aa_linetoFCVTZS Vd.2D,Vn.2D + XTNVector convert then truncate — different value

Same source line, same input, two different integers. A scalar path saturates; a vectorized path converts-then-truncates. The glyph's start point and its line segments now disagree about where they are in fixed-point space.

This is why "just add a bounds check" misses the lesson. The defect lives in the gap between the C abstract machine and the code the optimizer actually produces. Apple's fix clamps the value before the cast so neither lowering can ever see an out-of-range double.

3
Bounding-box corruption
Propagation

The diverging coordinates flow into aa_add_edges, which tracks the path's bounding box by comparing consecutive points. When one endpoint carries a wrapped int32, the delta subtraction overflows and the wrong branch is taken — so the box fails to expand to cover the real extent of the glyph:

// aa_add_edges — bbox tracking
int32_t dx = new_x - cur_x; // wraps on int32 overflow if (dx < 1) { if (ctx->bbox_min_x > new_x) ctx->bbox_min_x = new_x; if (ctx->bbox_max_x < cur_x) ctx->bbox_max_x = cur_x; } else { if (ctx->bbox_min_x > cur_x) ctx->bbox_min_x = cur_x; if (ctx->bbox_max_x < new_x) ctx->bbox_max_x = new_x; }

Result: a bounding box that reports a glyph as far narrower than it truly is.

4
The undersized coverage buffer
The bug realized

In aa_cache_render, the width in pixels is derived straight from that corrupted box, and the per-scanline coverage buffer is sized from it:

// aa_cache_render — coverage allocation
width_px = (bbox_max_x − bbox_min_x) / 4096; coverage = (width_px > 1015) ? malloc(4 * (width_px + 16)) // heap path : alloca(4 * (width_px + 16)); // stack path

An artificially small width_px yields a buffer too small for the edges the rasterizer is about to process. The allocation can land on the heap (malloc) or the stack (alloca) depending on size — giving an attacker a choice of corruption primitive.

5
The out-of-bounds write
Impact

As the rasterizer walks scanlines accumulating 16-bit alpha-coverage values, the real path edges extend past the undersized buffer. It keeps writing coverage increments beyond the allocation — a controlled out-of-bounds write. In the PoC this surfaces as an EXC_BAD_ACCESS crash; in a real exploit it is the primitive you build a chain on.

What the defender should take away
  • Trigger is pure data: a font inside a PDF, no user action beyond a preview.
  • Corruption target is attacker-influenceable (stack or heap) via glyph geometry.
  • Apple patched >20 instances of the clamp across 8 aa_* functions — the whole rasterizer family was exposed.
// the patch — clamp before the cast
if (v < -1073737729.0) return -1073737729; if (v > 1073737729.0) return 1073737729; // value can no longer leave the safe range before narrowing
⛓️

The Rendering Attack Chain

PHASE 06

From the app that previews the file to the overflowing write, every link is a legitimate system call. The chain below is the exact path the crafted glyph travels.

GLYPH RENDER PATH — EVERY HOP IS A LEGITIMATE CoreGraphics CALL
StageFunctionRole
EntryCGContextShowGlyphsAtPositionsApp asks CoreGraphics to draw glyphs at positions
Dispatchripc_DrawGlyphs → draw_glyph_bitmapsResolves each glyph to a bitmap render job
RasterizeCGGlyphBitmapCreateWithPathAndDilationBuilds the glyph path; invokes the AA rasterizer
Convertaa_moveto / aa_lineto → aa_double_to_fixedCoordinate conversion — the differential overflow
Sizeaa_add_edges → aa_cache_renderCorrupt bbox → undersized coverage buffer
Impactaa_cache_render scanline loop16-bit coverage writes past allocation = OOB write
🧪

From Crash to Code Execution

PHASE 07

Calif released a working PoC, but it is important to be precise about what it does — and what it does not.

P1
What the public PoC delivers
Reality check

The published harness generates a minimal PDF and a matching TrueType font that reliably crash unpatched iPhones and Macs. The repository includes font-generation scripts, a sample harness and a Makefile to build the crashing files. The researchers are explicit: this is a crash, not code execution — "going from this to code execution is another exercise entirely."

// conceptual repro flow (from the published harness)
$ make # build crafted font + minimal PDF $ open crash.pdf # preview on UNPATCHED device → EXC_BAD_ACCESS # crash backtrace lands inside the aa_* rasterizer / aa_cache_render

Only generate or detonate the PoC on isolated, consented test devices you own. Never send a crash file to a device you do not control — crashing someone's phone is an attack, not a test.

P2
The gap to a real exploit
Assessment

Weaponization means turning the undersized-buffer OOB write into a controlled primitive, defeating ASLR and modern iOS allocator mitigations, and chaining to a sandbox escape — the kind of engineering a well-resourced spyware vendor already demonstrated in the attacks Apple cites. A public crash PoC lowers the bar for others to start that work and raises the near-term risk of copycat denial-of-service abuse. Patch posture is the only reliable defense.

🕵️

The Mercenary-Spyware Pattern

PHASE 08

CVE-2026-86950 fits a now-familiar template: a memory-corruption bug in a universally reachable Apple parser, reported by a platform vendor, used against a small number of hand-picked targets. It is worth putting beside the chain Apple and Meta disrupted a year earlier, because the TTPs rhyme.

CVEComponentClassRole in pattern
CVE-2026-86950CoreGraphics (font/PDF)CWE-787 OOB write · CVSS 8.8Current — targeted, Meta-reported
CVE-2025-43300ImageIO (image parsing)OOB write · CVSS 10.02025 — exploited in zero-click targeted attacks
CVE-2025-55177WhatsApp linked-device syncAuthorization flaw · CVSS 5.42025 — chained to trigger processing of attacker content

In the 2025 campaign, reporting tied CVE-2025-55177 (WhatsApp) and CVE-2025-43300 (Apple ImageIO) together in zero-click attacks against fewer than 200 users. The 2026 bug lives in the same neighbourhood — a file-parsing primitive reachable through messaging — which is exactly why Meta's WhatsApp PDF-font hardening is such a telling signal. All three CVE identifiers above are confirmed present in NVD.

👤

Who gets hit

Journalists, dissidents, executives and officials — low-volume, high-value targeting, not mass campaigns.

🤫

How it arrives

A message or attachment that renders automatically; the parser does the attacker's work on preview.

🧩

Why parsers

Image/font/PDF decoders are enormous, shared, and run before any trust decision — ideal zero-click surface.

🔎

Indicators & Hunt Signals

PHASE 09

Honesty matters here: no public sample hashes, C2 domains or victim IOCs have been released for the in-the-wild attacks. Mercenary spyware is engineered to leave little on the device. What you can hunt for are the forensic artifacts of the crash and the exposure of unpatched devices.

SignalWhereMeaning
EXC_BAD_ACCESS crashiOS/macOS crash reportsFault backtrace inside aa_cache_render / CGGlyphBitmapCreateWithPathAndDilation
CoreGraphics in frame.ips crash logsRepeated crashes rendering a specific PDF/font = probing or failed exploit
Malformed embedded fontMail/MDM gateway PDF inspectionUnverifiable or extreme-coordinate fonts inside inbound PDFs
Device build < fixedMDM / Intune inventoryiOS < 26.7.1, macOS 26.x < 26.7.1, macOS 15.x < 15.8.1

Absence of a crash is not absence of compromise. A successful exploit does not crash — it renders cleanly and continues. Crash telemetry catches failed or untargeted attempts, not a working implant. Treat patch state as the primary control.

macOS — pull crash reports referencing the AA rasterizer
$ log show --predicate 'eventMessage CONTAINS "aa_cache_render"' --last 30d $ grep -rl "CGGlyphBitmapCreateWithPathAndDilation" ~/Library/Logs/DiagnosticReports/ $ grep -rl "EXC_BAD_ACCESS" ~/Library/Logs/DiagnosticReports/*.ips
📊

Detection & Fleet Queries

PHASE 10

For a near-zero-click device bug, "detection" is mostly exposure management: find the unpatched devices in your fleet before an operator does, and surface any crash artifacts your MDM collects. Pair each KQL with its Splunk equivalent.

DETECTS: Unpatched Apple devices below the fixed builds, from Intune / Defender device inventory.
KQL — Microsoft Intune / Defender (vulnerable Apple builds)
DeviceInfo | where OSPlatform in ("iOS", "macOS") | extend v = parse_version(OSVersion) | where (OSPlatform == "iOS" and v < parse_version("26.7.1")) or (OSPlatform == "macOS" and v >= parse_version("26.0") and v < parse_version("26.7.1")) or (OSPlatform == "macOS" and v >= parse_version("15.0") and v < parse_version("15.8.1")) | project DeviceName, OSPlatform, OSVersion, DeviceId, LastSeen | order by LastSeen desc
SPL — Splunk (vulnerable Apple builds from MDM inventory)
index=mdm sourcetype=device_inventory (os_platform=iOS OR os_platform=macOS) | eval build=replace(os_version,"[^0-9.]","") | eval vuln=case( os_platform=="iOS" AND cidrmatch("0","0") AND version_compare(build,"26.7.1")<0, "yes", os_platform=="macOS" AND version_compare(build,"26.0")>=0 AND version_compare(build,"26.7.1")<0, "yes", os_platform=="macOS" AND version_compare(build,"15.0")>=0 AND version_compare(build,"15.8.1")<0, "yes", true(), "no") | search vuln=yes | table host, os_platform, os_version, last_seen
DETECTS: Crash telemetry whose fault frame points at the CoreGraphics AA rasterizer — failed or probing exploitation.
KQL — crash events referencing the rasterizer
DeviceEvents | where ActionType == "ProcessCrash" or ActionType has "Crash" | where AdditionalFields has_any ("aa_cache_render", "CGGlyphBitmapCreateWithPathAndDilation", "CoreGraphics") | where AdditionalFields has "EXC_BAD_ACCESS" | summarize crashes = count() by DeviceName, bin(Timestamp, 1h) | where crashes >= 2 // repeated render crashes = probing
SPL — crash telemetry referencing the rasterizer
index=endpoint (sourcetype=osquery_crashes OR sourcetype=mdm_crash) ("aa_cache_render" OR "CGGlyphBitmapCreateWithPathAndDilation" OR "CoreGraphics") "EXC_BAD_ACCESS" | stats count AS crashes by host, _time span=1h | where crashes>=2 | sort - crashes
DETECTS: Inbound PDFs carrying embedded fonts, at the mail/proxy layer — surface for closer font inspection.
SPL — inbound PDFs with embedded fonts (gateway hunt)
index=email sourcetype=mail_gateway attachment_type="application/pdf" | where like(attachment_meta, "%/FontFile%") OR like(attachment_meta, "%TrueType%") | stats count by sender, recipient, subject, attachment_name | sort - count

Font embedding in a PDF is common and mostly benign — do not block on it. Use these hits to prioritize sandbox detonation and to focus deep font-structure validation (extreme coordinate values, malformed glyf tables) rather than as a standalone alert.

🎯

MITRE ATT&CK Mapping

PHASE 11
TacticTechniqueIDHow it applies
Initial AccessPhishing: Spearphishing AttachmentT1566.001Crafted PDF delivered as an attachment
Initial AccessDrive-by CompromiseT1189Web-delivered font/PDF rendered on preview
ExecutionExploitation for Client ExecutionT1203OOB write in CoreGraphics during glyph render
ExecutionUser Execution: Malicious FileT1204.002Victim opens/previews the malicious document
Defense EvasionExploitation (memory corruption, no on-disk payload)T1211Clean render on success leaves minimal artifacts
Impact (DoS)Endpoint Denial of ServiceT1499Public PoC crashes unpatched devices
🛡️

Mitigation & Hardening

PHASE 12
M1
Patch — the only reliable fix
Do first

Update every Apple device to a fixed build and force it through MDM. There is no configuration workaround for a memory-corruption bug in a system renderer.

  • 1
    iOS / iPadOS → 26.7.1
  • 2
    macOS Tahoe (26.x) → 26.7.1
  • 3
    macOS Sequoia (15.x) → 15.8.1
macOS — check current build against fixed
$ sw_vers --productVersion # confirm 26.7.1 / 15.8.1 or later $ softwareupdate -l # list and stage available updates
M2
Lockdown Mode for high-risk users
Harden

For the exact population this bug targets — executives, journalists, officials, anyone plausibly of interest to a mercenary operator — enable Lockdown Mode. It strips risky attachment and preview handling and has repeatedly blunted this bug class, making it meaningfully harder to reach the vulnerable parser.

Settings › Privacy & Security › Lockdown Mode › Turn On
M3
Reduce the preview surface
Defense in depth
  • 1
    Enforce minimum-OS compliance in MDM; quarantine devices below the fixed builds from sensitive resources.
  • 2
    Detonate inbound PDFs with embedded fonts in a sandbox before delivery to high-risk mailboxes.
  • 3
    Keep WhatsApp and other messaging apps current — Meta's added PDF-font validation only protects updated clients.
  • 4
    Collect iOS/macOS crash reports centrally so rasterizer faults are visible to the SOC, not stuck on the device.
Remediation complete when
  • Fleet inventory shows zero devices below 26.7.1 / 15.8.1.
  • Lockdown Mode is enforced for designated high-risk users.
  • Crash-report collection is live and the rasterizer hunts return clean.
📚

Sources & References

PHASE 13
NVD — CVE-2026-86950 (CoreGraphics out-of-bounds write, CVSS 8.8) Calif — "The Great Glyph Grift" root-cause analysis & PoC SecurityWeek — Apple patches Meta-reported zero-day linked to sophisticated attack SecurityAffairs — Public PoC released for CVE-2026-86950 SANS ISC — Apple emergency patch diary (CVE-2026-86950) CISA — Known Exploited Vulnerabilities Catalog NVD — CVE-2025-43300 (Apple ImageIO, prior zero-click pattern) NVD — CVE-2025-55177 (WhatsApp linked-device sync)

Hunting CVE-2026-86950 across your Apple fleet?

Run the file hashes and artifacts from any suspected spyware incident through the CyberHawk IOC Scanner, and track live zero-day activity on the Threat Intel feed. Building mobile incident-response playbooks? The CyberHawk SOP library covers zero-day exploitation and endpoint compromise response end to end.

◈ Stay Connected

Follow CyberHawk Threat Intel for threat intelligence, deployment guides and hands-on SOC tooling content.

🌐 Website ▶️ YouTube ▶️ YouTube (2) 𝕏 Twitter / X ♪ TikTok ✈️ Telegram
🔍 IOC Scanner 🛠️ Live Tools 📚 Courses 🚨 Threat Intel 📝 Blog 📋 SOPs

"They can't exploit you if you are the Exploit."