## https://sploitus.com/exploit?id=B02F492E-B304-5A76-9965-EE78FFF5A5E6
# CVE-2026-2796 + CVE-2026-2768 β Escape the Wasm Box
Full-chain Firefox exploitation research: a WebAssembly type confusion for
**renderer code execution**, chained toward a parent-process bug for a
**sandbox escape**. Both bugs were fixed in **Firefox 148** (MFSA-2026-13);
the target here is a Firefox 148-nightly tree @ `2fbc0748c4` (2026-01-14),
which predates both fixes.
- **CVE-2026-2796** (Bug 2013165): JIT miscompilation / signature type
confusion in SpiderMonkey's WebAssembly import optimization.
- **CVE-2026-2768** (Bug 2014101): sandbox escape β unvalidated IPC data
drives an out-of-bounds write in the **parent process**'s IndexedDB code.
## Chain architecture
```
page loads crafted wasm module
β
CVE-2026-2796: Function.prototype.call.bind unwrap skips signature check
β β i64 β (ref $t) confusion β addrOf/fakeobj
β β fake WasmArrayObject β arbitrary R/W in the CONTENT process
β β forged WasmFuncRef β hijack call target ([funcref+0x38])
βΌ
native code exec INSIDE the sandboxed content process (sbLevel 3)
β (sandbox blocks exec/fork β need a parent bug)
βΌ
CVE-2026-2768: forge IndexedDB add/put IPC with out-of-range
mAutoIncrementKeyOffsets (ParamTraits validates nothing)
β β parent writes 8 bytes at attacker-controlled offset
βΌ
memory corruption in the UNSANDBOXED parent process = full escape
```
## What's demonstrated
| Demo | Where | Result |
|---|---|---|
| `poc/shell/poc-crash.js` | js shell | `0xDEADBEEF` dereferenced as funcref β SIGSEGV at `0xdeadbf2f` |
| `poc/shell/poc-addrof.js` | js shell | arbitrary R/W self-tests pass |
| `poc/shell/poc-forge.js` | js shell | PC control: crash at planted canary |
| `poc/shell/poc-rce.js` | js shell | `system("id > /tmp/CVE-2026-2796-PWNED; open -a Calculator")` β file contains `uid=501(sid) ...`, Calculator pops |
| `poc/browser/stage1-browser.html` | Nightly (sbLevel 3 content) | arbitrary R/W in the sandboxed tab; forged funcref jumps to `0x4141414141414141` β **tab crashes, parent survives** |
| `poc/browser/stage1-browser-cmd.html` | Nightly (sbLevel 3 content) | leaks XUL base, resolves `posix_spawnp` (`0x187xxxxx`), calls it with `/bin/sh -c "touch /tmp/PWNED-FROM-CONTENT"` β **macOS sandbox denies the exec**: file not created, page unharmed β proof that content RCE alone β command execution |
| `poc/browser/sandbox-proof.html` | Nightly (sbLevel 3 content) | native exec *within* sandbox rules: `getpid()` returns the tab's real PID (matches `ps`), and raw libc `write(1, ...)` lands in the browser's terminal log β no fork/exec, no file opens |
| `poc/browser/stage2-trigger.html` | Nightly | pure-JS reachability of the parent bug path (auto-increment index keys `[1,2,3,4]`) |
See [docs/full-escape.md](docs/full-escape.md) for the stage-2 root-cause
analysis (fix diffs, IPC serialization, exploitation strategy).
## Building the vulnerable targets
```sh
# Tree: mozilla-firefox/firefox @ 2fbc0748c4 (2026-01-14, pre-FF148)
# 1) js shell (stage-1 development, unsandboxed):
cd js/src && ../../configure --enable-debug --enable-optimize \
--without-intl-api --enable-project=js && cd _obj && make -j8
# 2) full browser (stage 2). mozconfig:
# export CC=/usr/bin/clang ; export CXX=/usr/bin/clang++
# ac_add_options --enable-application=browser
# ac_add_options --disable-debug --enable-optimize
# ac_add_options --disable-crashreporter --disable-updater --disable-tests
# ac_add_options --enable-sandbox
# ac_add_options --without-wasm-sandboxed-libraries
# requires: node, cbindgen, rustc >= 1.87, macOS CLT SDK
# local build notes:
# - private header sys/fileport.h shim added to objdir dist/include/sys/
# - one compile guard added: NSGlassEffectView (macOS 26 SDK symbol) wrapped
# in #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 260000 in widget/cocoa/
# nsCocoaWindow.mm (build-environment fix, no security impact)
```
Run browser PoCs: launch `obj-browser/dist/Nightly.app` with a profile that
sets `browser.dom.window.dump.enabled=true`, open the HTML files over
`file://`, watch stdout for `dump()` output. Tab crash appears as
`process exited on signal 10` in the parent log.
## Offsets (macOS arm64)
`WasmArrayObject`: numElements @+16, data ptr @+24, inline data @+40.
`WasmFuncRef`: typeDef ptr @+0x40, call target @+0x38. `JSFunction` native
ptr @+0x20. js shell: `os_system` @ base+0x1a9f8, `system` GOT @
base+0x11d47b0. Browser: XUL base found by scanning back from a WebIDL
native code pointer (`console.log` JSFunction +0x20) to the `0xfeedfacf`
Mach-O magic; `_posix_spawnp` GOT @ XUL+0x9bb7d30, `_getpid` GOT @
XUL+0x9bb7600, `_write` GOT @ XUL+0x9bb87e0. Fake-array windows must
live in an out-of-line (malloc'd) array β inline/nursery objects get moved
by GC during long scans.
## Scope / honest limitations
Renderer code execution via CVE-2026-2796 is fully demonstrated (shell and
browser). The sandbox escape analysis of CVE-2026-2768 is source-verified
against the fix diff; the live end-to-end parent-corruption trigger is a
work in progress (see docs). This research is for defensive/educational use;
the vulnerabilities are patched in current releases.
## References
- [MFSA-2026-13](https://www.mozilla.org/security/advisories/mfsa2026-13/)
- [NVD: CVE-2026-2796](https://nvd.nist.gov/vuln/detail/CVE-2026-2796)
- CVE-2026-2796 fix: mozilla-firefox/firefox commit `e2acef67`
- CVE-2026-2768 fix: mozilla-firefox/firefox commit `c5dea6ec`
## Disclaimer
For security research, education, and defensive testing only. Do not use
against systems you do not own or have explicit authorization to test.