Firefox Site Isolation (Project Fission): Architecture, Trade-offs, and Operational Reality
Firefox's Project Fission (Firefox 93+) isolates cross-origin documents into separate OS processes to mitigate Spectre-class attacks. Covers per-eTLD+1 design, IPC bridges, trust boundaries, verification via about:processes, failure modes, and future design pressures.
27 Jul 2025, 06:05 UTC

The Problem: Transient-Execution Attacks Break Same-Origin Policy in Shared Memory
Spectre and Meltdown showed that CPU speculative execution can leak data across security boundaries inside a single address space. Browsers that map multiple origins into one process — even with same-origin policy checks in JavaScript — cannot prevent microarchitectural side channels from reading cross-origin secrets like cookies, tokens, or rendered pixels. Firefox's answer is Project Fission, shipped in Firefox 93 (2021), which moves the isolation boundary from the JS engine to the OS process.
Requirements Driving the Design
- Defend against Spectre-class leaks: Cross-origin data must never share a virtual address space where transient execution could expose it.
- Enforce same-origin policy at the OS level: The kernel's process isolation becomes the ultimate backstop.
- Maintain web compatibility: Legacy patterns —
window.open,postMessage, synchronousdocument.domainrelaxation — must still work, or sites break. - Bound memory growth: Each new process costs 30–80 MB baseline plus per-frame overhead. Unbounded process creation on iframe-heavy pages would OOM low-memory devices.
Smallest Suitable Design: Per-Effective-Top-Level-Origin Processes
Fission does not implement full site-per-process (one process per frame). Instead, it groups by eTLD+1 (effective top-level domain plus one label — e.g., example.com, github.io). All same-origin subframes share a single content process. Cross-origin iframes get their own process. The browser (chrome) process remains the privileged broker for process lifecycle, permissions, network stack, and IPC routing.
IPC Bridges
Two primary IPC actors mediate cross-process DOM access:
- PBrowser — owned by the browser process; manages tab lifecycle, navigation, permissions, and process creation.
- PContent — per-content-process actor; handles DOM mutations, script execution, and messaging to other content processes via the browser process.
When a cross-origin iframe loads, PBrowser spawns a new content process, initializes its PContent, and wires the frame's BrowsingContext to the new actor. postMessage and window.open route through the browser process, which enforces COOP/COEP policies before delivering messages.
Trust and Data Boundaries
| Boundary | Trust Assumption | Enforcement Mechanism |
|---|---|---|
| Browser ↔ Content | Browser trusts no content process | Sandbox: seccomp-bpf (Linux), Seatbelt (macOS), AppContainer (Windows) |
| Content ↔ Content (cross-origin) | Zero trust; no shared address space | Separate OS processes; IPC via browser process only |
| Content ↔ Content (same-origin) | Full trust — same security principal | Shared process; direct DOM access |
| Network/Storage layer | Partitioned per origin | Cookie jars, Cache, IndexedDB, LocalStorage keyed by eTLD+1 |
Cross-origin data never shares a process. Explicit sharing requires Cross-Origin-Opener-Policy: same-origin (COOP) and Cross-Origin-Embedder-Policy: require-corp (COEP) headers — without them, the browser process forces same-process grouping for opener/openee relationships to preserve legacy window.opener access.
Operational Checks You Can Run Today
Verify Process-to-Origin Mapping
Open about:processes in Firefox 93+. Each row shows PID, process type, and the origin(s) it hosts. Confirm that https://example.com and https://other.com in the same tab show distinct PIDs. Subframes from https://sub.example.com share the example.com process.
Toggle Fission and Observe Impact
# In about:config
fission.autostart.enabled = true # default on desktop
fission.autostart.enabled = false # disables Fission; restart required
After toggling, reload about:processes. With Fission off, a single content process hosts all frames. With Fission on, cross-origin iframes spawn new PIDs. This is the fastest way to measure memory delta on your workload.
Telemetry Signals to Monitor
fission.process_count— histogram of processes per sessionfission.oom_crashes— OOM kills attributed to content processesfission.ipc_latency_ms— round-trip latency for cross-process DOM calls
Access via about:telemetry → search "fission". In CI, web-platform-tests for COOP/COEP should pass > 95%.
Failure Modes and Mitigations
Process Explosion on Iframe-Heavy Pages
Sites embedding dozens of cross-origin iframes (ad tech, social widgets) would spawn unbounded processes. Fission caps at ~8–12 content processes per tab group (exact cap varies by platform and memory). Beyond the cap, new cross-origin frames fall back to an existing shared process, weakening isolation but preventing OOM. Check about:processes — you'll see multiple origins listed under one PID when the cap engages.
Memory Pressure on Low-RAM Devices
Fission adds ~10–20% memory overhead vs. non-Fission. On devices with < 2 GB RAM, Firefox may auto-disable Fission (fission.autostart=false) at startup. You can override in about:config, but expect OOM crashes on memory-constrained workloads.
Legacy Synchronous APIs Break Isolation
document.domain = "example.com" (the setter) disables Fission for that document and its same-origin frames — they rejoin a shared process to allow synchronous DOM access. Enterprise apps relying on this run unisolated. Synchronous XHR and alert()/prompt() in cross-origin frames also force same-process grouping via heuristics.
IPC Deadlocks and Browser Process Stalls
If the browser process blocks (e.g., on disk I/O or a synchronous IPC call from another content process), all content processes stall. Mitigation: async IPC everywhere, but legacy sync messages remain for some APIs. Monitor fission.ipc_latency_ms spikes.
Sandbox Escape CVEs
Windows AppContainer sandbox has known GPU process escape CVEs (e.g., CVE-2022-3019). The sandbox is defense-in-depth, not an absolute boundary. Keep Firefox updated; the browser process remains the ultimate trust anchor.
Conditions That Would Change the Design
- Hardware mitigations mature: If Intel eIBRS, AMD STIBP, or future CPU features reliably eliminate Spectre-class leakage, the isolation granularity could relax — fewer processes, lower memory.
- Wasm GC / Wasm Components: In-process sandboxing via WebAssembly's type-safe, capability-based model could replace some process boundaries for sandboxed workloads.
- OS memory-pressure signals: Android LMK, Windows Job Objects, or cgroups v2 notifications could drive dynamic process merging/unmerging instead of static caps.
- New side-channel classes: Port contention, cache-way partitioning, or DRAM row-hammer variants might require per-frame (not per-origin) isolation, reversing the consolidation trend.
Practical Verification Checklist
- Open
about:processes— confirm distinct PIDs per top-level origin. - Set
fission.autostart.enabled=falseinabout:config, restart, compare process count and memory (about:memory). - Load a test page with 20 cross-origin iframes — verify process count caps and fallback via
about:processes. - Run
./mach wpt cross-origin-opener-policy/ cross-origin-embedder-policy/— expect > 95% pass. - Check
about:telemetryforfission.oom_crashes> 0 on your user base — signals memory pressure.
Limitations to Accept
- Same-origin subframes share a process — cross-subframe leaks via same-origin policy gaps (e.g.,
document.domainrelaxation, prototype pollution) remain possible. - COOP/COEP headers are required for optimal isolation; without them, opener relationships force same-process grouping.
- Memory overhead is real — budget 10–20% more RAM for typical multi-tab sessions.
- Windows AppContainer is not a silver bullet; GPU process escapes exist.
Bottom Line
Fission is a pragmatic, shipped architecture that moves the trust boundary to the OS process for cross-origin content while accepting same-origin sharing and legacy opt-outs. It's not full site-per-process, and it's not free on memory. But for the threat model it addresses — Spectre-class transient execution — it's the smallest suitable design that keeps the web working. Verify with about:processes, monitor telemetry, and plan for the caps on iframe-heavy pages.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.