How Browser Exploits Work: A Case Study of CVE-2025-43529 (DarkSword iOS Chain)
Introduction
On 19 March 2026, Google’s Threat Intelligence Group (GTIG) with simultaneous analyses from Lookout and iVerify, disclosed DarkSword which is a one-click iOS exploit kit that chains six vulnerabilities to take a fully-patched-until-recently iPhone from “tapped a bad link” to “attacker has kernel read/write” in seconds. Three of the six bugs were zero-days at the time of disclosure. The entire chain is written in JavaScript with no native shellcode anywhere and that was unusual enough to warrant its own post on that alone.
This article is the first of two. Here we walk through the browser exploit portion of DarkSword with stages 1 through 3, ending the moment the attacker breaks out of Safari’s renderer process. Kernel escalation (stages 4 and 5) will be covered in a follow-up.
The audience we’re writing for: mobile security engineers, pentesters, and students who are comfortable with mobile security fundamentals but have never sat down with a browser-exploit chain before. We’re going to be specific about the pieces with facts like process names, WebKit tiers, actual ARM instructions, which files in the exploit kit do what, and all this without assuming prior knowledge of renderer internals. If a term trips you up, the glossary below has you covered.
Quick glossary
Skim this once, come back to it as needed.
- WebContent — the iOS Safari process (
com.apple.WebKit.WebContent) that actually renders the page: parses HTML, applies CSS, runs JavaScript. Heavily sandboxed. Often called the renderer. - GPU process — Safari’s separate process (
com.apple.WebKit.GPU) for hardware-accelerated drawing and WebGL. Looser sandbox than WebContent; the stage-3 escape target. - JavaScriptCore (JSC) — Apple’s open-source JavaScript engine, running inside every WebContent instance.
- JIT (Just-In-Time compiler) — component that takes frequently-run JavaScript and compiles it to native ARM64 machine code on the fly.
- JSC tiers: LLInt → Baseline → DFG → FTL — JSC’s four execution tiers, from slow-but-safe interpretation to heavily-optimized native code. The DarkSword JIT bugs live in the DFG tier.
- Type confusion — a bug class where the engine treats a value as one type while it is actually another; in a JIT, a classic path to raw memory R/W.
addrof/fakeobj— two primitives every JS-engine exploit constructs first.addrof(x)leaks the memory address of JS objectx.fakeobj(a)makes the engine treat addressaas if it were a JS object.- Sandbox — OS-enforced cage restricting what a process can do (filesystem, network, IPC, syscalls). Each WebKit process runs under a dedicated sandbox profile.
- Sandbox escape — pivoting from a tighter-sandboxed process to a looser-sandboxed (or unsandboxed) one, usually via a bug in an IPC endpoint the target process exposes.
- XPC / Mach messages — the IPC plumbing Apple platforms use for inter-process communication. WebContent talks to the GPU process over XPC.
- PAC (Pointer Authentication Codes) — an ARMv8.3-A feature Apple uses pervasively on A12+ silicon. Function pointers carry a cryptographic signature (embedded in their high bits); the CPU refuses to jump through a pointer whose signature doesn’t check out.
- PPL / SPTM — Page Protection Layer and Secure Page Table Monitor. Mitigations that make it prohibitively expensive to run attacker-introduced native code. They are the reason DarkSword stays in pure JavaScript.
- ANGLE — Almost Native Graphics Layer Engine. The open-source translation layer that turns WebGL 1/2 calls into the platform’s real graphics API (Metal on iOS). Originally from Google’s Chromium project; used by Safari/WebKit as well.
- OOB (Out-of-Bounds) write — writing memory you don’t own. Classic memory-corruption primitive.
- Zero-click vs one-click — zero-click exploits fire with no user interaction (e.g. iMessage). One-click requires a single tap, usually on a link — which is what DarkSword does.
- Watering hole — attacker compromises, spoofs, or buys traffic to a site the target audience is likely to visit, and plants the exploit there instead of going after targets individually.
What is DarkSword?
DarkSword is a one-click watering hole kit where a victim taps a link to a compromised or look-alike site, the page silently loads an obfuscated JavaScript loader, and by the time the loader has finished probing the device it has already chosen and fired the right exploit payload.
- 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, and 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. Most iOS exploit chains eventually drop native ARM64 shellcode, which means they have to defeat Apple’s PPL and SPTM mitigations that police native-code execution. DarkSword’s authors decided it was cheaper to stay in JavaScript the whole way and sidestep that category of defence entirely.
- 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 where 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 are not independently discovering these bugs; they all acquired the same kit, and it was built to target whatever was common and unpatched during the winter of 2025–2026.

Image credit: Google Cloud Threat Intelligence Group, “The Proliferation of DarkSword: iOS Exploit Chain Adopted by Multiple Threat Actors” (19 March 2026). Screenshot of the publicly available blog post header.
The delivery flow, end to end:
The attackers did not hack Snapchat. They just built a look-alike share page (snapshare[.]chat) and seeded links to it. Here’s a screenshot of the actual decoy as captured by Google’s Threat Intelligence Group:

Image credit: Google Cloud Threat Intelligence Group, “The Proliferation of DarkSword: iOS Exploit Chain Adopted by Multiple Threat Actors” (19 March 2026). Reproduced under fair use for technical commentary.
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 cooperating processes, each locked in its own sandbox, talking to each other over IPC.
On iOS, Safari runs roughly like this:
- UI process — the “lobby.” Draws the tab bar, address bar, bookmarks. This is the process you see in Activity Monitor as
Safarion macOS or the foreground app on iOS. It does not, itself, run page JavaScript. - WebContent (
com.apple.WebKit.WebContent) — the renderer. One per tab (roughly). Parses HTML, applies CSS, executes JavaScript through JSC, and lays out pixels. Everything untrusted lives here. It has the tightest sandbox profile of any WebKit process. - GPU process (
com.apple.WebKit.GPU) — hardware-accelerated drawing, WebGL via ANGLE, video decoding. Brokers access to the GPU because WebContent is not allowed to touch it directly. - Networking process (
com.apple.WebKit.Networking) — actually makes HTTP requests; WebContent asks politely over XPC. Not directly relevant to DarkSword but worth knowing exists. mediaplaybackd— system-wide media daemon. Not part of Safari per se, but it turns out to be an attractive stage-4 pivot target because it has broader filesystem and IPC access than the GPU process.- XNU kernel — underneath everything.
The processes communicate almost exclusively over XPC, which rides on Mach messages at the kernel level. XPC endpoints are the natural attack surface for sandbox escapes: WebContent can’t read your files, but it can send messages to the GPU process, and if the GPU process mishandles one of those messages, it’s game over.
Between every one of these components sits a sandbox which is effectively a locked door defined by a Sandbox Profile Language (.sb) profile. 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. Its profile assumes everything it touches is hostile.

macOS Activity Monitor filtered by “WebKit” is a live proof that Safari is not one program. Each com.apple.WebKit.WebContent is a separate sandboxed renderer process; com.apple.WebKit.GPU is the shared GPU broker; com.apple.WebKit.Networking handles HTTP for all tabs.
Inside WebContent lives JavaScriptCore (JSC) which is Apple’s JavaScript engine, open-sourced under Source/JavaScriptCore/ in the WebKit tree. 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, and why is it exploit-prone?
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 memorises a shorthand and delivers it instantly. That’s a JIT (Just-In-Time compiler) in one paragraph: watch which code runs a lot and compile that “hot” code straight into native machine instructions for speed.
JSC has four tiers that a function can move through as it runs:
- LLInt (Low-Level Interpreter) — a portable, slow interpreter. Every function starts here.
- Baseline JIT — simple, template-style code generation. Few optimisations; good enough for warm code.
- DFG JIT (Data Flow Graph) — an optimising JIT. Builds a data-flow graph, performs speculation (“this variable is always an Int32, so I’ll skip the type check”), and inserts guards to bail back to lower tiers if the assumption breaks.
- FTL JIT (Faster Than Light) — a heavier optimiser built on top of JSC’s own B3 backend (and historically LLVM). Runs on the hottest code.
The relevant tier for DarkSword is the DFG. That’s where speculation happens, and speculation is what JIT exploits typically target. If an attacker can convince the DFG to emit code under a false assumption and then, at runtime, change the shape of memory so the assumption no longer holds. The compiled code will run with no safety checks on data that is no longer what it was promised to be.
That is a type confusion, and it is a direct path to reading and writing memory inside the WebContent process.
The DarkSword JIT bugs
DarkSword ships two separate JIT exploits and picks the right one based on the victim’s iOS version (it probes via navigator.userAgent in the loader):
- CVE-2025-31277 — a JIT optimisation / 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 the DFG tier. Used against iOS 18.6 – 18.7. Patched in iOS 18.7.3 and iOS 26.2.
Why two exploits? Because the exact memory layout and structure IDs the primitives rely on change between WebKit builds. The exploit kit compiles one exploit per supported WebKit and picks the right one at runtime.
Both exploits end up building the two primitives that every JS-engine exploit you’ll ever read about construct first:
// conceptual, not working code
// addrof — tell me where this JS object lives in memory
const leakedAddr = addrof(victimObject);
// fakeobj — pretend this piece of memory IS a JS object
const puppet = fakeobj(attackerControlledAddress);
// combine the two and you can read and write anywhere
// in the WebContent process.
Under the hood, addrof and fakeobj are usually constructed by exploiting a mismatch between how JSC stores object data (its “butterfly”) and how it types values (inline tagged 64-bit words). By causing one array to be typed as holding doubles while an adjacent one is typed as holding objects, and then writing a chosen bit pattern into the first, so you can read back the bit pattern as an object pointer (fakeobj), or observe an object pointer as a 64-bit double (addrof). That’s the sketch; the real exploit is much fiddlier and depends on the exact DFG bug used to create the type mismatch.
Stack those two primitives and you effectively have a debugger attached to your own browser tab: arbitrary memory read, arbitrary memory write, all inside the WebContent process.
That is the first win. But it is not enough on its own. Everything so far lives inside WebContent, and WebContent is the tightest sandbox in the building.
For a canonical deep-dive on JSC exploitation, Saelo’s “Attacking JavaScript Engines” in Phrack 70 remains the reference. For the modern version with butterflies and structure IDs, Phrack 71 has a follow-up. The WebKit source is open at webkit.org/source.
Stage 2 — Calling real code: defeating PAC
Arbitrary read/write inside the renderer is powerful but limited. You can read memory, you can change memory, but on modern Apple silicon you can’t call anything. You cannot call a system function, not a C library routine, and certainly not a syscall. The CPU itself refuses to jump through a pointer you didn’t earn.
The mechanism is Pointer Authentication Codes (PAC), introduced in ARMv8.3-A and baked into every A12-and-later Apple chip.
How PAC works, in one paragraph
Function pointers on iOS carry a cryptographically-computed signature in their high bits. For this iOS uses a 11-bit or larger PAC, depending on VA width. The signature is derived from a secret per-process key, a modifier which is typically a context value like a stack address, and the pointer itself which is computed by the PACIA/PACIB/PACDA/PACDB family of instructions. Before the CPU follows an authenticated branch (BLRAA, RETAA, etc.), it uses AUTIA/AUTIB to verify the signature; if the verification fails, the pointer is poisoned with a non-canonical bit pattern, and the next dereference traps. Net effect: an attacker with arbitrary read/write still can’t forge a valid call target, because they don’t know the per-process PAC keys.
PAC is a huge part of why “arbitrary R/W on iOS” does not immediately mean “arbitrary code execution.”
The DarkSword PAC bypass
DarkSword’s stage 2 is CVE-2026-20700, a zero-day in dyld (the user-mode dynamic linker), patched in iOS 26.3. Without giving the full primitive, the idea is this: dyld performs a lot of signing itself in the normal course of resolving lazy bindings and stubs. The bug lets an attacker trick dyld into emitting a PAC-signed pointer for an address they control, effectively turning dyld into a PAC-signing oracle.
With that in hand, the earlier arbitrary R/W primitive becomes arbitrary native function calling: the attacker can synthesise a valid signed pointer to any function in the process, install it wherever JSC will dereference it, and have the CPU happily branch through it. They can now call real iOS APIs from their JavaScript-level foothold.
Stage 3 — Breaking out of the renderer (WebContent → GPU)
Let’s take stock. We now have:
- Arbitrary read/write inside WebContent.
- Arbitrary native function calling, courtesy of the
dyldPAC oracle.
What we don’t have is the ability to do anything interesting. The WebContent sandbox profile denies us the file system, most sockets, almost all syscalls, and the vast majority of Mach services. Safari’s designers expected us to end up here. So we need to punch a hole into a neighbouring apartment that has more privilege.
This is the sandbox escape, and it is the stage at which a browser exploit turns into a weapon.
Why WebGL, and what ANGLE is
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) which is originally a Google/Chromium project that translates WebGL 1/2 calls into the platform’s real graphics API. On iOS, ANGLE translates WebGL into Metal. When a page calls gl.drawElements(...), a chain of events fires:
- JSC calls through to WebKit’s WebGL binding in WebContent.
- WebContent marshals the call into an XPC message.
- The message is sent to the GPU process over a dedicated XPC service.
- The GPU process hands the call to its copy of ANGLE, which validates the arguments, translates the call into Metal, and submits it to the driver.
Step 3 is an IPC boundary across sandboxes. Step 4’s argument validation is the security boundary that has to be right, because the GPU process is running with elevated privileges relative to WebContent, and so any memory corruption inside it is a sandbox escape.
The DarkSword ANGLE bug
CVE-2025-14174 is a zero-day in ANGLE: one specific WebGL operation failed to validate its parameters sufficiently before passing them down to the Metal layer. By issuing a crafted call from JavaScript, an attacker triggers an out-of-bounds write 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. This is a separate JavaScript payload the kit fetches only after the earlier stages have succeeded. That modular staging is a common pattern: keep each stage small, version-gated, and independently replaceable so you can swap out individual CVEs as Apple patches them.
At the end of stage 3, the attacker has code execution inside com.apple.WebKit.GPU which is a looser sandbox than WebContent, though still meaningfully sandboxed, and is ready to pivot deeper into mediaplaybackd and then the kernel.
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 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:

Image credit: Google Cloud Threat Intelligence Group, “The Proliferation of DarkSword: iOS Exploit Chain Adopted by Multiple Threat Actors” (19 March 2026). Reproduced under fair use for technical commentary.
Why this chain is pure JavaScript
The single biggest design choice in DarkSword is a negative one: the authors never transition to native code. No ARM64 shellcode is ever loaded into memory and flipped to executable. Every line the attacker runs, from stage 1 all the way to the kernel payload, is JavaScript executing inside JSC’s normal JIT pipeline which the CPU already trusts because the JIT is an Apple-signed component operating in Apple-signed memory.
From a mitigation perspective that is enormous. Apple has spent nearly a decade building defences specifically against attacker-introduced native code:
- W^X (write-xor-execute) enforcement makes it impossible to have memory that is writable and executable at the same time.
- Code Signing Enforcement refuses to execute pages that don’t trace back to an Apple-signed binary.
- Page Protection Layer (PPL) guards the kernel’s view of executable code pages from a compromised kernel itself.
- Secure Page Table Monitor (SPTM), introduced on A15-and-later / M-series silicon, prevents even a privileged kernel attacker from rewriting page tables to remap pages as executable.
Each of these exists to kill the classic pattern: drop shellcode, flip it executable, jump to it. DarkSword simply does not take that path, so those defences have nothing to police.
What the kit looks like inside
Instead of shellcode, DarkSword ships a pure-JavaScript post-exploitation runtime that sits on top of the primitives from stages 1 and 2 (arbitrary R/W and the dyld PAC oracle). Analysis of the kit’s files reveals a layered, modular library that wouldn’t look out of place in a legitimate application:
| Module | Role |
|---|---|
Chain/Native.js | Low-level memory access — read8, read64, write*, wrapped with ArrayBuffer / typed-array helpers. |
Chain/OffsetsStruct.js | Version-gated struct field offsets for iOS internals (WebCore, JSC, libSystem). |
TaskRop/VM.js | Mach VM manipulation — vm_allocate, vm_protect, mach_vm_remap invoked natively from JS. |
TaskRop/RemoteCall.js | Arbitrary native function call, riding on the PAC bypass from stage 2. |
TaskRop/PAC.js | Helpers for signing, stripping, and forging PAC’d pointers via the dyld oracle. |
FileUtils | POSIX-style filesystem API (open, read, stat, unlink) — implemented as native-call wrappers, not syscall() shellcode. |
Driver/Driver.js | Top-level orchestrator gluing stages together. |
InjectJS.js | Loads the next-stage JS module into whatever process the previous stage escaped into. |
MigFilterBypassThread.js | Circumvents the MIG message filter Apple applies on sensitive XPC entitlements — needed to reach certain privileged Mach services from a renderer. |
In other words: the attacker never runs code the CPU treats as “attacker-introduced.” They run code the CPU treats as JavaScriptCore, because it literally is — emitted by JSC’s own JIT from a stream of attacker-supplied JavaScript that the engine was tricked into trusting.
The trade-off
Nothing is free. Staying in JavaScript binds the exploit tightly to specific JSC internals: object shapes, structure IDs, butterfly geometry, JIT-cache layout — all of which shift between WebKit builds. Every change requires re-tuning the primitives, which is why DarkSword ships per-version workers (rce_worker_18.6.js, rce_worker_18.7.js, and so on): the bug may carry across builds, but the primitive construction on top of it does not. What the kit buys with that maintenance burden is a clean sidestep of Apple’s entire native-code defence stack, and the kit’s authors clearly decided that was a bargain worth making.
Put in historical context, this is a real departure. FORCEDENTRY (NSO Group, 2021) delivered native shellcode via a CoreGraphics JBIG2 parser bug, and a large chunk of the exploit’s complexity went into defeating iMessage’s BlastDoor sandbox and code signing so that shellcode would actually run. Operation Triangulation (2023) executed native code from iMessage and needed hardware-feature abuse to reach the kernel. DarkSword demonstrates a different path entirely: stay in JavaScript, and everything above the JIT boundary is a problem somebody else already solved for you.
And then it keeps going — stages 4 and 5
From the GPU process, DarkSword fires CVE-2025-43510 which is 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 VFS layer) gives the attacker arbitrary kernel read/write. At that point the game is over. Both bugs and their exploitation we’ll walk through 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. The activity started in November 2025 and the last patches landed in iOS 26.3 in March 2026:

Image credit: Google Cloud Threat Intelligence Group, “The Proliferation of DarkSword: iOS Exploit Chain Adopted by Multiple Threat Actors” (19 March 2026). Reproduced under fair use for technical commentary.
-
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, and intermediate releases like 18.7.2 and 18.7.3 closed most CVEs but not all. If you are 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 and it disables enough of the JavaScriptCore features (notably the JIT) that the stage-1 exploits have nothing to land on. It is a blunt instrument that breaks or degrades some legitimate features, but it is 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 loaders that version-probe
navigator.userAgent/navigator.platformbefore fetching a second-stage payload. On the device side: anomalous XPC / Mach IPC patterns betweencom.apple.WebKit.WebContentandcom.apple.WebKit.GPUwhic is especially unusually large messages on the WebGL service path. -
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 (github.com/google/angle); 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/en-us/126793
- Apple Platform Security — “Pointer Authentication Codes” — 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.