Back to Intelligence

CVE-2026-86974: Apple Safari jsToWasm Type Confusion (ZDI-26-830) — Detection and Remediation Guide

SA
Security Arsenal Team
October 28, 2026
8 min read

The Zero Day Initiative has published ZDI-26-830, tracking CVE-2026-86974: a type confusion vulnerability in Apple Safari's jsToWasm IC (inline cache) entrypoint handling that allows remote, unauthenticated attackers to execute arbitrary code on affected systems. ZDI rates it CVSS 8.8 (High). Exploitation requires user interaction — the target must visit a malicious page or open a malicious file — but that's the standard delivery model for every browser drive-by campaign we've responded to over the past decade. A watering hole, a malvertising redirect, or a phishing link is all it takes.

This vulnerability class matters to defenders for two reasons. First, WebAssembly JIT/type-confusion bugs in browser engines are the exact primitive class that exploit developers chain into full renderer compromises — a successful type confusion gives an attacker controlled memory read/write, which is the foundation of every modern browser exploit chain. Second, Safari exploitation reaches macOS workstations and, given WebKit's mandatory use on iOS, potentially the entire Apple mobile estate. If your executives and developers carry Apple devices — and they do — this is in your threat model.

Technical Analysis

Affected Products and Scope

Per the ZDI advisory (ZDI-26-830):

  • Product: Apple Safari (WebKit browser engine)
  • Component: jsToWasm inline cache (IC) entrypoint in the JavaScript engine's WebAssembly call path
  • CVE: CVE-2026-86974
  • CVSS: 8.8 (High)
  • Authentication: None required
  • User interaction: Required — target must visit a malicious page or open a malicious file
  • Platform impact: Safari on macOS; because Apple mandates WebKit for all iOS/iPadOS browsers, the underlying engine exposure extends to the mobile fleet pending Apple's patch guidance

How the Vulnerability Works (Defender's View)

The flaw lives in the inline cache entrypoint for JavaScript-to-WebAssembly calls (jsToWasm). Inline caches are a JIT optimization: when JS repeatedly calls a Wasm function, the engine caches the call path and skips expensive type/arity checks. A type confusion here means the engine generates or invokes an entrypoint that assumes one object/function type while the attacker has substituted another. From a defender's perspective, the attack chain looks like this:

  1. Delivery: Victim loads attacker-controlled HTML/JS — phishing link, compromised site, malvertising, or a malicious file opened in Safari.
  2. Trigger: Malicious JavaScript constructs Wasm modules and JS call patterns that groom the IC into a confused state, causing the engine to treat an object as a different type at the Wasm entrypoint.
  3. Primitive: Type confusion → controlled type reinterpretation → out-of-bounds or arbitrary read/write within the WebContent (renderer) process.
  4. Post-exploitation: Attackers typically attempt sandbox escape and payload staging — spawning shells, writing persistence, or reaching out to C2. On macOS, watch for the com.apple.WebKit.WebContent process doing anything other than rendering.

Exploitation Status

At the time of this writing, ZDI has published the advisory with a CVSS 8.8 rating; the summary does not indicate confirmed in-the-wild exploitation or CISA KEV inclusion. Treat it as weaponization-likely: 8.8-rated, unauthenticated, browser-delivered type confusions historically move from disclosure to exploit-kit integration quickly, and WebKit bugs are consistently targeted by commercial spyware vendors and APT actors alike. Do not wait for a KEV listing to act.

Detection & Response

Browser zero-days are hard to detect at the point of memory corruption — the exploit runs inside the JIT. The realistic detection surface is post-exploitation behavior: the WebContent/renderer process behaving like an attacker's foothold. The detections below target that surface and are deliberately narrow to stay deployable.

YAML
---
title: Safari WebKit Renderer Spawning Shell or Scripting Interpreter
id: 3f8c2e14-9b6a-4d51-ae72-0c4f8a2b7d91
status: experimental
description: Detects Safari WebContent processes spawning shells or scripting interpreters, consistent with post-exploitation behavior following browser compromise such as CVE-2026-86974 jsToWasm type confusion exploitation.
references:
  - http://www.zerodayinitiative.com/advisories/ZDI-26-830/
  - https://attack.mitre.org/techniques/T1203/
author: Security Arsenal
date: 2026/04/06
tags:
  - attack.execution
  - attack.t1203
  - attack.t1059
logsource:
  category: process_creation
  product: macos
detection:
  selection_parent:
    ParentImage|endswith:
      - '/com.apple.WebKit.WebContent'
      - '/com.apple.WebKit.Networking'
      - '/Safari'
  selection_child:
    Image|endswith:
      - '/bash'
      - '/zsh'
      - '/sh'
      - '/python'
      - '/python3'
      - '/osascript'
      - '/curl'
      - '/wget'
      - '/nc'
      - '/perl'
      - '/ruby'
  condition: selection_parent and selection_child
falsepositives:
  - Rare; WebKit extensions or developer tooling may legitimately invoke osascript
triage: Investigate immediately - renderer processes should never spawn interactive shells
level: critical
---
title: WebKit Process Writing to macOS Persistence Locations
id: 6e1a4c92-7d38-4f26-b854-1a9d3e5c7f08
status: experimental
description: Detects Safari or WebKit processes writing launch agents/daemons or login persistence artifacts, a common post-exploitation step after browser renderer compromise such as CVE-2026-86974.
references:
  - http://www.zerodayinitiative.com/advisories/ZDI-26-830/
  - https://attack.mitre.org/techniques/T1543/
author: Security Arsenal
date: 2026/04/06
tags:
  - attack.persistence
  - attack.t1543.001
  - attack.t1543.004
logsource:
  category: file_event
  product: macos
detection:
  selection_process:
    Image|endswith:
      - '/com.apple.WebKit.WebContent'
      - '/com.apple.WebKit.Networking'
      - '/Safari'
  selection_target:
    TargetFilename|contains:
      - '/Library/LaunchAgents/'
      - '/Library/LaunchDaemons/'
      - '~/Library/LaunchAgents/'
      - '/Library/StartupItems/'
  condition: selection_process and selection_target
falsepositives:
  - None expected in normal operation
level: critical
KQL — Microsoft Sentinel / Defender
// Hunt: Safari/WebKit renderer spawning shells, scripting engines, or download tools
// Covers macOS endpoints onboarded to Microsoft Defender for Endpoint
let suspiciousChildren = dynamic(["/bin/bash", "/bin/zsh", "/bin/sh", "/usr/bin/python3", "/usr/bin/osascript", "/usr/bin/curl", "/usr/bin/wget", "/bin/nc", "/usr/bin/perl", "/usr/bin/ruby"]);
DeviceProcessEvents
| where TimeGenerated > ago(7d)
| where InitiatingProcessFileName has_any ("com.apple.WebKit.WebContent", "com.apple.WebKit.Networking", "Safari")
   or InitiatingProcessFolderPath has_any ("WebKit.framework", "Safari.app")
| where FileName has_any ("bash", "zsh", "sh", "python", "osascript", "curl", "wget", "nc", "perl", "ruby")
   or ProcessCommandLine has_any ("curl ", "wget ", "osascript", "/bin/bash", "/bin/zsh")
| project TimeGenerated, DeviceName, AccountName, InitiatingProcessFileName,
          InitiatingProcessCommandLine, FileName, ProcessCommandLine, SHA256
| order by TimeGenerated desc
KQL — Microsoft Sentinel / Defender
// Hunt: unexpected outbound network connections from WebKit renderer processes
// Renderer talking directly to rare external IPs post-page-load is a C2/staging signal
DeviceNetworkEvents
| where TimeGenerated > ago(7d)
| where InitiatingProcessFileName has_any ("com.apple.WebKit.WebContent", "com.apple.WebKit.Networking")
| where RemoteIPType == "Public"
| summarize ConnectionCount = count(), DistinctPorts = dcount(RemotePort),
            Ports = make_set(RemotePort), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated)
         by DeviceName, RemoteIP, RemoteUrl, InitiatingProcessFileName
| where DistinctPorts > 3 or ConnectionCount > 50
| order by DistinctPorts desc
VQL — Velociraptor
-- Velociraptor artifact: hunt macOS endpoints for shells or download tools
-- spawned by Safari/WebKit processes (post-exploitation indicator for CVE-2026-86974)
LET suspicious_children = '/(bash|zsh|sh|python3?|osascript|curl|wget|nc|perl|ruby)$'

SELECT Pid, Ppid, Name, Exe, CommandLine, Username, CreateTime
FROM pslist()
WHERE Exe =~ suspicious_children
  AND Ppid IN (
    SELECT Pid FROM pslist()
    WHERE Name =~ 'WebContent|WebKit|Safari'
  )

Triage Guidance

If any detection fires:

  1. Isolate the host — do not reboot; capture memory first if you have an IR retainer or Velociraptor deployed.
  2. Collect browsing artifacts — Safari History.db, Downloads.plist, and WebKit cache to reconstruct the delivery URL for threat intel and blocklisting.
  3. Check for persistence — LaunchAgents, LaunchDaemons, cron, and unexpected mdfind-invisible directories in user Library folders.
  4. Scope laterally — if the host had corporate credentials cached (Keychain, browser sessions, SSH keys), assume credential exposure and rotate.

Remediation

1. Patch — Highest Priority

  • Apply the latest Safari and macOS updates via System Settings → General → Software Update across the entire fleet. Apple ships WebKit fixes both in macOS point releases and standalone Safari updates — install both channels.
  • For iOS/iPadOS, push the latest update via MDM. Because all iOS browsers run WebKit, every browser app inherits this exposure until patched.
  • Monitor the ZDI-26-830 advisory and Apple Security Releases for the specific fixed version numbers, and verify deployment against them. Do not assume auto-update covered your fleet — audit it.

2. Verify and Enforce via MDM

Bash / Shell
#!/bin/bash
# verify_safari_patch.sh - Audit Safari/WebKit versions across macOS fleet
# Run via MDM (Jamf/Kandji/Intune) as a recurring script or extension attribute

echo "=== CVE-2026-86974 Safari/WebKit Patch Verification ==="

# macOS version
sw_vers

# Safari version
SAFARI_VER=$(/usr/bin/defaults read /Applications/Safari.app/Contents/Info.plist CFBundleShortVersionString 2>/dev/null)
SAFARI_BUILD=$(/usr/bin/defaults read /Applications/Safari.app/Contents/Info.plist CFBundleVersion 2>/dev/null)
echo "Safari Version: ${SAFARI_VER} (Build ${SAFARI_BUILD})"

# WebKit framework build
WEBKIT_VER=$(/usr/bin/defaults read /System/Library/Frameworks/WebKit.framework/Resources/Info.plist CFBundleVersion 2>/dev/null)
echo "WebKit Framework Build: ${WEBKIT_VER}"

# Pending updates check
PENDING=$(/usr/sbin/softwareupdate -l 2>&1 | grep -ci 'safari\|macos')
if [ "$PENDING" -gt 0 ]; then
  echo "[WARNING] Pending Apple updates detected - remediation incomplete:"
  /usr/sbin/softwareupdate -l 2>&1 | grep -i 'safari\|macos'
  exit 1
else
  echo "[OK] No pending Safari/macOS updates"
fi

# Automatic update enforcement status
AUTO_UPDATE=$(/usr/bin/defaults read /Library/Preferences/com.apple.SoftwareUpdate AutomaticCheckEnabled 2>/dev/null)
echo "Automatic Update Check Enabled: ${AUTO_UPDATE:-not configured - enforce via MDM}"

3. Compensating Controls (Pre-Patch Gap Window)

  • Disable JavaScript in Safari for high-risk users (executives, finance, admins) as a temporary measure — it breaks modern web use, so scope it tightly, but it fully neutralizes JIT-triggered bugs like this one.
  • Route Safari traffic through your secure web gateway / DNS filtering and block newly registered domains, known malvertising networks, and uncategorized sites.
  • Enforce MDM restrictions preventing users from installing unmanaged browsers as a "workaround" — an unmanaged Chromium instance with its own patch lag is not an improvement.
  • Deploy the detections above before patching completes; the post-exploitation telemetry has value regardless of patch state.

4. Longer-Term Hardening

  • Ensure Lockdown Mode is available as an option for targeted individuals (journalists, executives facing spyware-class threats) — it disables JIT compilation in WebKit, which defeats this entire vulnerability class at the cost of some site functionality.
  • Validate that your EDR covers macOS with process-lineage visibility; many estates still have weaker Apple telemetry than Windows, and browser exploitation exploits exactly that gap.
  • Add WebKit zero-days to your threat model for watering-hole and phishing scenarios in tabletop exercises.

Bottom line: an 8.8, unauthenticated, renderer-level type confusion in the default browser of every Mac and iPhone in your organization is a patch-this-week item, not a next-cycle item. Patch, verify with the script above, deploy the renderer-behavior detections, and treat any Safari-spawned shell as an incident until proven otherwise.

Related Resources

Security Arsenal Penetration Testing Services AlertMonitor Platform Book a SOC Assessment vulnerability-management Intel Hub

Is your security operations ready?

Get a free SOC assessment or see how AlertMonitor cuts through alert noise with automated triage.