Firefox SpiderMonkey WebAssembly GC RCE: One Typo, Full Renderer Compromise

Executive Summary

A security researcher recently disclosed a Remote Code Execution vulnerability in Mozilla Firefox's SpiderMonkey JavaScript engine, caused by a single-character typo introduced during a WebAssembly GC refactoring commit. The vulnerability — a classic type confusion via incorrect bitwise operator — allows an attacker to achieve RCE inside the Firefox renderer process by serving a crafted WebAssembly page.

With Firefox installed on over 200 million devices globally, the blast radius of this vulnerability is enormous. The attack requires no authentication, no special privileges, and only minimal user interaction: visiting a malicious URL. The full technical writeup and PoC were published at kqx.io, where it immediately went viral with 130+ upvotes on r/netsec. Mozilla was notified prior to disclosure.

If you run Firefox, update immediately. Mozilla's rapid patching cadence means a fix is either already available or imminent.

CVSS Breakdown: The Attack Profile

This vulnerability is estimated at CVSS 8.8 (High), with the potential to be rated higher if a sandbox escape is chained on top of renderer RCE:

  • Attack Vector (AV:N): Network — exploitable by serving a crafted Wasm page from any web server
  • Attack Complexity (AC:H): High — requires triggering Ion JIT optimization + specific GC heap conditions, though PoC demonstrates this is reliable with a short warm-up loop
  • Privileges Required (PR:N): None — attacker only needs to serve a web page
  • User Interaction (UI:R): Required — victim must visit the malicious URL (drive-by, phishing, malvertising)
  • Scope (S:U): Unchanged — renderer RCE stays within the sandboxed renderer; a sandbox escape would upgrade this to Critical
  • Confidentiality (C:H): High — full access to renderer memory including sensitive tab content
  • Integrity (I:H): High — arbitrary code execution in renderer process
  • Availability (A:H): High — browser tab/process crashable or fully controlled

The "High" complexity rating is the only thing keeping this from Critical — but as the researcher demonstrates, the Ion JIT optimization path is predictably triggered by looping a warm-up function ~1000 times, and GC movement is trivially invoked via explicit minorgc() calls in test harnesses. A real exploit would embed this warm-up in the Wasm module itself.

Technical Deep Dive: One Character, Maximum Damage

The Guilty Commit

Everything traces back to a single refactoring commit — fcc2f20e35ec — which modified the handling of WebAssembly GC array metadata in js/src/wasm/WasmGcObject.cpp. The commit was supposed to store a tagged forwarding pointer (with the LSB set to 1) when the GC moves an Out-of-Line (OOL) Wasm array. The code was written like this:

oolHeaderOld->word = uintptr_t(oolHeaderNew) & 1;

It should have been:

oolHeaderOld->word = uintptr_t(oolHeaderNew) | 1;

The difference is a single character: & (AND) instead of | (OR). The intent of the original code, as the accompanying comment explicitly states, was to set bit 0 of the forwarding pointer — the classic "tagged pointer" trick to distinguish a forwarding address from a real header value. Using | 1 achieves this by setting the LSB. Using & 1 does the opposite: since all heap pointers are at minimum 8-byte aligned, uintptr_t(oolHeaderNew) & 1 is always 0. The code faithfully writes a zero word into the old buffer header instead of a tagged forwarding pointer.

SpiderMonkey's OOL vs. Inline Array Architecture

To understand why this matters, it helps to understand how SpiderMonkey stores WebAssembly GC arrays. Firefox's SpiderMonkey implements the Wasm GC proposal, which supports garbage-collected array types. For small arrays (zero to ~32 bytes), element data is stored inline (IL) immediately after the WasmArrayObject header — no separate allocation needed. For larger arrays, SpiderMonkey allocates a separate out-of-line (OOL) block managed by js::gc::BufferAllocator.

Critically, SpiderMonkey distinguishes between these two layouts at runtime by examining the LSB of the header word:

static inline bool isDataInline(uint8_t* data) {
  const OOLDataHeader* header = (OOLDataHeader*)data;
  header--;
  uintptr_t headerWord = header->word;
  return (headerWord & 1) == 0;  // LSB=0 means Inline; LSB=1 means OOL forwarding pointer
}

With the typo in place, when the GC moves an OOL array, it writes 0 into the old buffer's header. The old buffer now passes isDataInline() — LSB is 0 — so SpiderMonkey believes the old OOL block is an inline array. This is a type confusion: the engine reads array elements from an address derived from inline layout arithmetic, but the memory region belongs to a completely different allocation. The result is controlled out-of-bounds read/write, which is the foundation of a reliable exploitable primitive.

The Exploitable Condition

Two constraints narrow the attack surface slightly:

  1. The bug is only triggerable in code paths optimized by Ion, SpiderMonkey's advanced JIT compiler. It does not occur in the Baseline compiler. This means the Wasm function must be sufficiently "hot" to trigger Ion compilation — typically a few hundred to a thousand iterations. This is trivially achievable by any attacker-controlled webpage.
  2. The GC must physically move the OOL array — either Nursery→Nursery or Nursery→Tenured. This requires a minor GC to fire during or between Wasm executions. Again, trivially achievable: attackers can allocate memory to force GC pressure, and modern Wasm-heavy pages do this naturally.

The researcher's PoC from the disclosure demonstrates a reliable crash within seconds using a 128-element Wasm byte array, an explicit minorgc(true) call between each iteration, and a 1000-iteration warm-up loop. Real exploits would not need the explicit GC call — allocation pressure from the array creation loop alone would trigger the necessary GC cycles.

From Type Confusion to RCE

Once the type confusion is established — OOL array treated as IL — the attacker controls which memory region is interpreted as the array's element storage. A standard WebAssembly array read or write operation then becomes an arbitrary read or write primitive at an attacker-controlled address. The path from here to full RCE in the renderer process follows well-established browser exploitation patterns:

  1. Leak heap address: Use the confusion primitive to read a known structure, obtaining a heap layout reference point
  2. Corrupt JIT code or function pointer: Overwrite a code pointer in a nearby JIT-compiled function or a vtable entry in a Wasm object
  3. Redirect execution: Trigger the corrupted function, gaining PC control
  4. ROP chain / shellcode: Standard renderer code execution from this point

The researcher confirmed achieving code execution in the Firefox renderer process. The renderer is sandboxed (Firefox uses process isolation), so a full system compromise would additionally require a sandbox escape — but renderer RCE alone gives attackers access to all content in the compromised tab, including credentials, session cookies, and sensitive form data.

Attack Tools for Security Researchers

Understanding and testing browser vulnerabilities like this one benefits enormously from dedicated tooling. For Wasm fuzzing and JavaScript engine research, Burp Suite Professional provides essential proxy and interception capabilities for analyzing how Wasm modules are served and executed. The The Browser Hacker's Handbook by Wade Alcorn et al. covers the full spectrum of browser exploitation techniques, including memory corruption in JavaScript engines — essential background for understanding SpiderMonkey internals. For hands-on lab work, a dedicated test machine running a vulnerable Firefox build is strongly recommended over your main browser.

Real-World Attack Scenarios

This vulnerability is particularly dangerous because the attack surface is the entire web:

Drive-By Exploitation

An attacker hosts a malicious webpage containing a crafted Wasm GC module. Any Firefox user who navigates to the URL — directly, via a redirect, or via a malicious iframe embedded on a legitimate-looking page — triggers the exploit. The attack completes within seconds of page load (the Ion warm-up is fast). No clicks, no downloads, no plugins required beyond Firefox itself with WebAssembly enabled (the default).

Malvertising

An attacker purchases an ad slot on a high-traffic advertising network and serves the exploit payload as an advertisement. Thousands of Firefox users on legitimate websites execute the Wasm payload without any indication of compromise. This is historically how browser zero-days are most efficiently monetized.

Spear Phishing

For targeted attacks, a convincing phishing email links to a page that first serves legitimate content (a realistic document preview, a login page mock) and simultaneously loads the Wasm exploit in a background worker. The victim sees only the legitimate page content while the renderer is compromised.

Compromised CDN / Supply Chain

An attacker who has compromised a CDN or JavaScript delivery network could inject the Wasm payload into legitimate sites serving millions of Firefox users simultaneously. A single CDN compromise becomes a mass exploitation event.

Detection and Threat Hunting

Browser-Level Signals

  • Unexpected Firefox renderer process crashes (look for WasmGcObject, WasmArrayObject, obj_moved in crash stack traces)
  • Firefox content process spawning unexpected child processes (shell, Python, netcat)
  • Unusual network connections originating from the Firefox renderer process (not the main process)
  • Firefox crash reporter telemetry spikes in enterprise environments

Network-Level Signals

  • HTTP responses serving .wasm files followed immediately by outbound C2 connections from the browser
  • Wasm files with unusually small size but containing GC array operations and explicit GC invocations
  • Suspicious Content-Type: application/wasm delivery from low-reputation or newly-registered domains
  • Renderer crash telemetry followed by HTTP POST to external domains (data exfiltration pattern)

EDR/SIEM Rules

  • Alert on: Firefox content process spawning cmd.exe, powershell.exe, sh, or bash
  • Alert on: firefox.exe (content process) making direct DNS queries to previously-unseen domains
  • Alert on: Memory allocation anomalies in js-executable-memory region of Firefox process space

For comprehensive endpoint visibility and browser exploit detection, the Hacking: The Art of Exploitation, 2nd Edition provides foundational knowledge of memory corruption primitives that all detection engineers should understand. Combining this with an isolated test environment for safe exploit analysis is the recommended approach for IR teams.

Immediate Remediation

1. Update Firefox Immediately (Critical — Do This Now)

Mozilla's security response team patches browser RCE vulnerabilities in days, sometimes hours. Check for updates:

  • Desktop: Firefox menu → Help → About Firefox → check for updates
  • Enterprise: Push the latest Firefox ESR via MDM (Intune, JAMF, SCCM) immediately
  • Android: Update via Google Play Store or the official Mozilla APK
# Verify current Firefox version
firefox --version

# Enterprise: Deploy latest ESR via winget (Windows)
winget upgrade Mozilla.Firefox.ESR

# Linux
sudo apt update && sudo apt upgrade firefox  # Debian/Ubuntu
sudo dnf update firefox                       # Fedora/RHEL

2. Short-Term Mitigation (if patching is delayed)

If immediate patching is not possible in a managed environment:

  • Disable WebAssembly: Navigate to about:config and set javascript.options.wasm = false. Note: this breaks WebAssembly-dependent web applications (many modern SaaS tools use Wasm for performance-critical code).
  • Disable JIT: Set javascript.options.baselinejit = false and javascript.options.ion = false to prevent Ion compilation. This breaks the trigger condition but severely degrades JavaScript performance.
  • Browser isolation: Route all web browsing through an isolated browser (e.g., Remote Browser Isolation) that does not run code locally.

3. Enterprise Response

  • Disable Firefox on unmanaged devices until patched
  • Review browsing logs for visits to newly-registered domains serving Wasm content in the past 7 days
  • Check endpoint telemetry for Firefox renderer process crashes concurrent with outbound connections
  • Consider temporarily routing Firefox through a proxy that blocks Content-Type: application/wasm responses from non-allowlisted domains

Bug Bounty Angle: What This Means for Hunters

The Firefox SpiderMonkey Wasm GC RCE is a masterclass in how catastrophic single-character bugs can be in memory-unsafe code paths. A few lessons for bug hunters:

Look for Typos in Recent Refactoring Commits

This bug was introduced by a routine refactoring commit — not a major feature addition. Code reviews often miss single-character mistakes in bitwise operations because the surrounding code looks semantically correct. When auditing open-source projects, prioritize recently-merged refactoring PRs, especially in memory management and GC-related code. The fix diff is deceptively tiny.

WebAssembly as an Attack Surface

As Wasm GC (garbage collection extension to WebAssembly) adoption grows across all major browsers, the attack surface for GC-related memory corruption is expanding. The bug class demonstrated here — type confusion between inline and out-of-line storage layouts — is a recurring pattern in GC implementations. Study the Wasm GC spec and look for similar discriminant/tag checks in V8 (Chrome) and JSC (Safari).

Mozilla's Bug Bounty Program

Mozilla pays between $500 and $15,000 for browser security vulnerabilities, with critical RCEs typically at the upper end. The researcher here found this by reading the Firefox source code while preparing a CTF challenge — a reminder that structured code review of open-source browsers is one of the highest-ROI activities in bug bounty research.

Essential Tools for Browser Research

For researchers targeting browser engines, the The Hacker Playbook 3 by Peter Kim covers advanced exploitation techniques relevant to browser attack chains, and a YubiKey 5 NFC Security Key is recommended for securing your own research accounts given that browser vulnerabilities can compromise researcher credentials too.

Disclosure Timeline

  • ~February 2026: Vulnerability discovered during Firefox source code review for CTF challenge preparation (TRX CTF 2026)
  • February 2026: Reported to Mozilla Security team via responsible disclosure
  • February 21–22, 2026: Full technical writeup published at kqx.io following disclosure coordination with Mozilla
  • February 23, 2026: Story goes viral on r/netsec (130+ upvotes, 96% ratio); Mozilla patch expected imminently

Mozilla's typical turnaround for reported browser RCEs is 7–14 days for a patch release. Given the public disclosure, a fix should already be in a Firefox security update or arriving within days.

Conclusion: The Terrifying Power of One Wrong Operator

The Firefox SpiderMonkey Wasm GC RCE is a reminder that the most dangerous vulnerabilities are often the simplest. A & where there should be a |. A zeroed word where a tagged pointer was expected. A memory layout discriminant returning the wrong answer. From that single character, a skilled researcher built a reliable type confusion primitive leading to full renderer code execution.

What makes this particularly sobering is the review process. The commit that introduced the bug was presumably reviewed by Mozilla engineers. The code is open source and audited continuously by the security community. Yet this typo survived until an independent researcher found it while browsing the codebase for CTF inspiration. It's a powerful argument for both continued investment in automated fuzzing (which should catch this class of bug) and structured code audits of GC-related code paths.

Immediate Action Checklist:

  1. ✅ Update Firefox to the latest version on all devices — right now
  2. ✅ Enterprise teams: push Firefox ESR update via MDM within the hour
  3. ✅ If patching is delayed: disable WebAssembly via about:config
  4. ✅ Hunt your logs: Firefox renderer crashes + outbound connections = potential compromise
  5. ✅ SOC teams: add EDR rules for Firefox content process spawning shells
  6. ✅ Bug hunters: study the Wasm GC spec and look for similar type discrimination bugs in V8/JSC

Advertisement