How Browser Exploits Work: A Case Study of CVE-2025-43529 (DarkSword iOS Chain)
Introduction
In March 2026, Google’s Threat Intelligence Group (GTIG), together with Lookout and iVerify, disclosed DarkSword — an iOS exploit kit that turns a single tap on a spoofed Snapchat share page into a full device takeover. It chains six different vulnerabilities to walk all the way from a JavaScript engine bug in Safari down to the kernel, and it does the entire job in pure JavaScript.
If you’ve never read a browser-exploit writeup before, those words probably all sound the same. This post is for you. We’ll use DarkSword as a case study to explain, in plain terms, how browser exploits work on a modern mobile device — what the “renderer” is, why a JavaScript bug can become an RCE, and how attackers pivot out of the browser’s sandbox. We’ll focus on the browser exploit chain specifically — the first three stages of DarkSword, ending when the attacker breaks out of Safari’s renderer. Kernel escalation (stages 4 and 5) will get a one-paragraph summary and a follow-up post of its own.
What is DarkSword?
DarkSword is a one-click watering hole exploit kit: victims visit a compromised or spoofed legitimate-looking site (the first confirmed campaign used snapshare[.]chat, a Snapchat-themed bait page), and that’s it — the chain fires in the background.
- Affected: iOS 18.4 through 18.7, with iOS 18.4 – 18.6.2 hit hardest (these devices lacked both the initial WebKit and kernel patches released in late 2025). iOS 18.7 was only partially vulnerable at first — a separate
rce_worker_18.7.jsmodule was needed to target it. - Delivery: compromised site → hidden
<iframe>→frame.html→rce_loader.js→ version-specific exploit. - Unique trait: every stage is written in pure JavaScript. That’s unusual. Most iOS chains eventually drop native ARM64 shellcode, which means they have to defeat Apple’s Page Protection Layer (PPL) and Secure Page Table Monitor (SPTM). DarkSword’s authors decided it was cheaper to stay in JavaScript the whole way.
- Actors: at least three distinct groups are using it in the wild — UNC6748, Turkey’s PARS Defense, and UNC6353. Victim clusters have been observed in Saudi Arabia, Turkey, Malaysia, and Ukraine.
- Final payloads: three iOS implants — GHOSTBLADE (bulk data miner), GHOSTKNIFE (backdoor), and GHOSTSABER (backdoor with arbitrary JS execution).
A detail that’s easy to miss: DarkSword is a “democratised” exploit kit — the code was leaked or sold to multiple independent groups (UNC6353, PARS Defense, and others). That’s why you see so many unrelated actors hitting the same iOS version bracket at the same time. They’re not independently discovering these bugs; they all bought or stole the same kit, and it was built to target whatever was common and unpatched during the winter of 2025 – 2026.
The delivery flow looks like this:
The attackers did not hack Snapchat — they built a look-alike share page and seeded links to it. Here’s a screenshot of the actual snapshare[.]chat decoy as captured by Google’s Threat Intelligence Group:

How a browser is actually built
Before we can talk about “a browser exploit”, we need to get one idea straight: a modern browser is not one program. It is several programs, talking to each other, each locked in its own cage.
Think of Safari on iOS as an apartment building:
- The UI process is the lobby. It draws the tab bar, the address bar, the settings — all the chrome you interact with.
- Each tab runs in its own renderer process, called WebContent on iOS. This is the apartment that actually opens the webpage you asked for. It parses HTML, applies CSS, runs JavaScript, and produces the pixels you see.
- The GPU process is the boiler room. It does hardware-accelerated drawing and video decoding on behalf of WebContent.
- A separate service called
mediaplaybackdhandles media decoding for the whole system. - Underneath all of this sits the kernel.
Between every one of these components there is a sandbox — a locked door. The WebContent sandbox is the most restrictive of the lot, because WebContent is the apartment where untrusted code (your JavaScript, their JavaScript, the ad network’s JavaScript) actually runs. It assumes everything it touches is hostile.
Inside WebContent lives JavaScriptCore (JSC) — Apple’s JavaScript engine. JSC is the part that actually takes the JavaScript on the page and turns it into ARM64 machine code your CPU can run. That translation is where our story starts.
Stage 1 — Getting code running: the JIT bug
The first question every browser exploit has to answer is: how do I get my attacker-controlled JavaScript to misbehave at the level of raw memory?
The answer, almost always, is the JIT compiler.
What’s a JIT?
Imagine a simultaneous interpreter at the UN. The first few times you say a sentence, she translates it word by word — slow, careful, safe. But if you keep repeating the same sentence, she memorizes a shorthand and delivers it instantly. That’s a JIT (Just-In-Time compiler): a component that watches which code runs a lot and compiles that “hot” code straight into native machine instructions for speed.
JSC has four tiers of execution: LLInt (a slow interpreter), Baseline (a simple JIT), DFG (an optimizing JIT), and FTL (a heavier optimizer). You don’t need to remember all four — just remember that DFG is an optimizer that makes assumptions. For example: “this variable is always an integer, so I can skip the type check.” If an attacker can make the optimizer commit to a false assumption and then quietly change the type, the compiled native code happily operates on the wrong kind of object — with no runtime check to catch it.
That is called a type confusion, and it is a direct path to reading and writing arbitrary memory inside the WebContent process.
The DarkSword JIT bugs
DarkSword ships two separate JIT exploits and picks the right one based on your iOS version:
- CVE-2025-31277 — a JIT optimization / type confusion bug in JavaScriptCore. Used against iOS 18.4 – 18.5. Patched in iOS 18.6.
- CVE-2025-43529 — a zero-day garbage collection bug in DFG. Used against iOS 18.6 – 18.7. Patched in iOS 18.7.3 and iOS 26.2.
Both exploits end up building two primitives that are the bread-and-butter of every JavaScript engine exploit you’ll ever read about:
// conceptual, not working code
// 'addrof' — tell me where this JS object lives in memory
let leaked = addrof(victimObject);
// 'fakeobj' — pretend this piece of memory IS a JS object
let puppet = fakeobj(attackerControlledAddress);
// combine the two and you can read and write anywhere
// in the WebContent process.
addrof tells you where a given JavaScript object is in memory. fakeobj lets you point the engine at a piece of memory and say “treat this as a JavaScript object.” Put them together and you effectively have a debugger attached to your own browser tab — you can read and write anywhere inside WebContent.
That is the first win. But it’s not enough on its own. Everything we’ve done so far lives inside the WebContent apartment, and WebContent is the most heavily locked apartment in the building.
For a deeper look at
addrof/fakeobjand heap grooming in JSC, Saelo’s “Attacking JavaScript Engines” in Phrack 70 is still the canonical reference.
Stage 2 — Calling real code: defeating PAC
Arbitrary read/write is powerful but limited. You can look at memory, you can change memory, but you can’t call anything — not a system function, not a C library routine. On modern Apple silicon (the A12 onward), the CPU itself refuses to jump to arbitrary addresses.
The mechanism is called Pointer Authentication Codes (PAC).
Think of every function pointer on iOS as a letter with a wax seal. Before the CPU accepts “jump to this address,” it checks the seal. Forge a letter without the right seal and the chip kills your process. PAC is implemented in hardware using ARMv8.3 instructions, and it is the single biggest reason why “read/write” on iOS doesn’t automatically mean “code execution.”
DarkSword’s stage 2 is CVE-2026-20700, a zero-day bug in dyld (the dynamic linker), patched in iOS 26.3. The bug lets the attacker generate PAC-signed pointers of their own, so they can hand the CPU a valid-looking seal for an address they control. Once that’s in place, the earlier arbitrary-R/W primitive becomes arbitrary native function calling — the attacker can now invoke real iOS APIs from their JavaScript-level foothold.
Why pure JavaScript? Staying in JS means the attacker never drops native shellcode, which means they never have to defeat Page Protection Layer (PPL) or Secure Page Table Monitor (SPTM) — two mitigations that only police native code execution. It’s a neat way to dodge a whole category of defense.
Stage 3 — Breaking out of the renderer (WebContent → GPU)
Let’s take stock. We now have:
- Arbitrary read/write inside WebContent.
- The ability to call real iOS functions via the PAC bypass.
What we don’t have is the ability to do anything interesting. The WebContent sandbox prevents us from reading files, opening sockets, or making most system calls. Safari’s designers expected us to end up here. So we need to punch a hole into a neighbouring apartment with more privileges.
This is the sandbox escape, and it is usually where a browser exploit becomes a weapon.
DarkSword’s first escape targets the GPU process. WebContent talks to the GPU process whenever a page does anything graphics-heavy — and the most common way a page does that is WebGL, the JavaScript API for 3D graphics in the browser. WebKit implements WebGL on top of ANGLE (Almost Native Graphics Layer Engine), an open-source translation layer that takes WebGL calls and turns them into something the platform’s real graphics stack understands.
The bug: CVE-2025-14174 — a zero-day in ANGLE where one specific WebGL operation did not validate its parameters properly. By calling it with crafted arguments from JavaScript, an attacker can trigger an out-of-bounds memory access inside the GPU process. Patched in iOS 18.7.3 and iOS 26.2.
In DarkSword’s code, the loader for this stage is called sbx0_main.js — a separate JavaScript payload that the exploit fetches only after the earlier stages have succeeded. That modular staging is a common pattern: keep each stage small, version-gated, and replaceable.
At the end of stage 3, the attacker has code execution inside the GPU process — which has looser sandbox restrictions than WebContent — and is ready to pivot deeper.
The full chain at a glance
| Stage | CVE | Component | What it gets you | Patched in |
|---|---|---|---|---|
| 1a | CVE-2025-31277 | JavaScriptCore JIT | RCE in WebContent (iOS 18.4 – 18.5) | iOS 18.6 |
| 1b | CVE-2025-43529 | DFG JIT (GC) — 0-day | RCE in WebContent (iOS 18.6 – 18.7) | iOS 18.7.3 / 26.2 |
| 2 | CVE-2026-20700 | dyld — 0-day | User-mode PAC bypass → arbitrary native calls | iOS 26.3 |
| 3 | CVE-2025-14174 | ANGLE / WebGL — 0-day | Sandbox escape WebContent → GPU | iOS 18.7.3 / 26.2 |
| 4 | CVE-2025-43510 | XNU (copy-on-write) | GPU → mediaplaybackd | iOS 18.7.2 / 26.1 |
| 5 | CVE-2025-43520 | XNU VFS (race) | Kernel read/write | iOS 18.7.2 / 26.1 |
Six bugs. Three of them were zero-days at the time of disclosure.
Google’s own infection-chain diagram lays out the same flow at a lower level, including the JavaScript file names for each stage:

And then it keeps going — stages 4 and 5
From the GPU process, DarkSword fires CVE-2025-43510 (a copy-on-write bug in the XNU kernel) to pivot into mediaplaybackd, a system daemon with much broader filesystem and IPC access. From there, CVE-2025-43520 (a kernel-mode race condition in XNU’s virtual filesystem layer) gives the attacker arbitrary kernel read/write — at which point the game is over. We’ll walk through both in a follow-up post.
Defence and takeaways
Google’s timeline of DarkSword observations and vulnerability patches gives a good sense of the window in which unpatched devices were exposed — activity started in November 2025 and the last patches landed in iOS 26.3 in March 2026:

- Update your phone. The two “known-good” targets are iOS 18.7.7 (the legacy fix Apple backported specifically for the 18.x branch, released late March / early April 2026) and iOS 26.3 (the modern branch). Anything below either of those should be treated as potentially vulnerable to at least part of the chain — intermediate releases like 18.7.2 and 18.7.3 closed most CVEs but not all. If you’re checking a fleet, ”≥ 18.7.7 or ≥ 26.3” is the rule to enforce.
- Can’t update right now? Turn on Lockdown Mode. Even on an unpatched iOS 18.4 – 18.7.x, Lockdown Mode reportedly blocks DarkSword — it disables enough of the JavaScriptCore features (notably the JIT) that the stage-1 exploits have nothing to land on. It’s a blunt instrument (breaks some normal features), but it’s the right emergency lever for anyone who can’t patch immediately.
- What to look for as a defender or researcher. On the network side: hidden iframes loading scripts from unrelated domains, and scripts that version-probe
navigator.userAgentbefore fetching a second-stage payload. On the device side: anomalous IPC patterns between WebContent and the GPU process. - What to study if you’re learning. Pick one layer and get comfortable before moving on — JavaScriptCore’s DFG tier is a great starting point for JIT internals; ANGLE’s validation code is short and readable; iOS sandbox profiles are a good way to understand what “sandboxed” concretely means. Our earlier post on reading iOS sandbox profiles is a good companion read.
Browser exploits look mysterious from the outside, but they follow a predictable arc: get code running in the renderer, turn read/write into real execution, break out of the sandbox, escalate. DarkSword is a textbook example — written textbook-neatly, in pure JavaScript, across six CVEs and three threat actors. The specific bugs will rotate out as Apple patches them. The shape of the chain will not.
References
Primary disclosure
- Google Cloud Threat Intelligence Group — “The Proliferation of DarkSword: iOS Exploit Chain Adopted by Multiple Threat Actors” (19 March 2026) — cloud.google.com
- Lookout Threat Intel — “Attackers Wielding DarkSword Threaten iOS Users” — lookout.com
- iVerify — “Inside DarkSword: A New iOS Exploit Kit Delivered via Compromised Legitimate Websites” — iverify.io
Apple advisories
- Apple — iOS 18.7.7 security release notes — support.apple.com
Get in Touch
Want to learn these techniques hands-on, or need help assessing your own mobile or AI stack? We run live and on-demand trainings, offer mobile-security certifications, and take on penetration-testing engagements. Pick the door that fits.
We respond within one business day. Visit our events page to see where we'll be next.