Sploitus

Exploit for Use After Free in Mozilla Firefox

githubexploit Β· 2026-08-11

Exploit Code

README74 lines
## https://sploitus.com/exploit?id=06514230-A3CA-56E0-BAAC-7A79F942B8A0
# CVE-2026-2766, but with wasm

**Status: validated crash PoC (UAF on a GC-managed ICScript), weaponization
in progress.**

A WasmBlazeFox-family chain on a 2026 bug: CVE-2026-2766, "JIT
miscompilation / use-after-free in the JavaScript Engine: JIT component",
fixed in Firefox 148 (MFSA 2026-13). The endgame is the same as
[CVE-2024-29943-but-with-wasm](https://github.com/SneakyNachos/CVE-2024-29943-but-with-wasm):
turn the primitive into control of a code pointer, and aim it at a WASM JIT
page full of shellcode constants.

## Root cause

From Mozilla's own regression test comments (bug 2013583, test landed in
hg 457b68097f81) and the `ICScript Lifetimes` SMDOC in `js/src/jit/JitScript.h`:

- During Ion trial inlining, a polymorphic call site transition calls
  `removeInlinedChild` β†’ the child's `ICScript` is removed from
  `inlinedChildren_` but is still referenced by the `InliningRoot`'s
  `inlinedScripts_` vector β€” and, fatally, by the stale
  `CallInlinedFunction` stub still sitting in the caller's IC chain.
- A compacting GC (`gczeal(14, 1)`, i.e. `ZealCompactValue` every
  allocation) moves/evacuates the orphaned ICScript while the stale stub
  chain keeps the old address.
- The next call through the old stub dereferences the stale ICScript
  pointer β†’ use-after-move. In ASAN/fuzzing builds the freed cell is
  poisoned with `0xe5`, giving a very readable crash.

## Crash evidence

Vulnerable build: mozilla-central rev `b3663be61a1a` (2026-01-15 nightly;
the fix landed between 2026-01-15 and 2026-02-09 β€” the Feb-09 nightly
survives). Shell: Taskcluster `linux64-fuzzing-asan-opt` jsshell for that
rev (needed for `gczeal`; release-opt shells lack it).

```
./js --ion-warmup-threshold=100000 poc.js

== ERROR: AddressSanitizer: SEGV on unknown address 0xe5e5e5e5e5e5e5e5
   The signal is caused by a READ memory access.
   #0-#3            compacting GC moves it; stale chain keeps old address
    -> reclaim the old cell with controlled bytes (size-class spray)
      -> baseline reads fake ICEntry -> fake ICStub -> fake code_ pointer
        -> jump into the WASM JIT page shellcode (f64.const immediates,
           FuncExport entry-offset overwrite β€” see the 2024-29943 repo)
```

Known constraints, honestly:

- The free window sits *inside* `outer(Inner, true)` in the PoC, so the
  reclaim spray has to be timed against zeal/allocator behavior, or the
  trigger restructured so a controlled allocation lands in the evacuated
  cell between free and use.
- Reclaim is size-class work: `ICScript` is a `TrailingArray` (variable
  size); the spray object must match the freed cell's class.
- A working gdb is basically mandatory to finish this; ptrace is broken
  under OrbStack's x86 emulation, so the next phase wants a native Linux
  x86-64 box (or a full-fat VM).

## Files

- `poc.js` β€” Mozilla's regression test (bug 2013583), verified to crash the
  2026-01-15 ASAN jsshell as shown above.

## References

- Advisory: MFSA 2026-13 (Firefox 148)
- Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=2013583 (restricted)
- Test landing: hg `457b68097f81`
- Sibling chains: https://github.com/SneakyNachos/CVE-2024-29943-but-with-wasm
  and https://github.com/SneakyNachos/CVE-2026-2764-but-with-wasm
- Technique origin: https://github.com/SneakyNachos/WasmBlazeFox