# JIT deopt guard omission on mutation

Optimizer bakes in a type/map/immutability fact; a mutation or deprecation path changes it without forcing deopt.

_Area: Memory corruption and native code. Seen in 5 disclosed reports; one confirmed bounty: $250,000; latest 2026-10-13. Updated 2026-11-07._

## How it works
An optimizing JIT compiles code against a fact it observed earlier: this variable holds an Int32Array, this object's map is stable, this number box is immutable, this array's `pop` has no side effects. To stay correct, the compiler must register a dependency so that if the fact ever stops being true, the optimized code is thrown away (deoptimized). The bug is a path that changes the fact without triggering that dependency: a reassignment the optimizer's check skips, a map that gets deprecated even though a predicate said it could not be, a prototype accessor that supplies a different type, a mutable box reused as a deopt literal. Optimized code then keeps running on a stale assumption and treats one type as another.

## Where it shows up
- Optimizer predicates like `CanBeDeprecated` or "should expect conventional index" checks, especially across flag combinations (pointer compression, unboxed doubles).
- Map transition/deprecation code that installs no code dependency for some field layouts.
- Guards that validate a variable's type at function entry but not after reassignment inside loops.
- Builtins assumed side-effect-free (`pop`, indexed access) where a prototype can supply accessors or differently-typed elements.
- Escape analysis that dematerializes an object but keeps a sub-allocation (backing store) alive, with paths that materialize the same activation twice.
- Deopt literals holding mutable boxes (HeapNumbers) that reconstructed objects then share.

## How to review
For every assumption the optimizer bakes in, find the mutation or deprecation path that could falsify it and confirm a dependency forces deopt. The invariant: any state change that invalidates a compiled assumption must either be impossible or registered as a deopt dependency. Check predicates against all flag combinations, not just the default build. Check that type guards are re-validated after reassignment, that side-effect-free builtins cannot reach prototype accessors, and that materialization never yields two objects sharing one backing store.

## How finders spotted it
- Reasoned about obligations a sandbox threat model imposes on downstream consumers, then hunted code treating a "detached" or "frozen" state as immutable [E1](https://bugbountylibrary.com/r/blog%3Axbow-com-labs-research-zero-to-calc-in-six-days-inside-xbow-chrome-full-chain.md).
- Patch analysis pointed to a flawed check in the optimizer's array-source handling (`GlobOpt::OptArraySrc` / `ShouldExpectConventionalArrayIndexValue`) [E2](https://bugbountylibrary.com/r/p0%3ACVE-2022-41128.md).
- Fuzzing with Fuzzilli and independent P0 analysis surfaced a type-confusion variant; the lesson is to audit JIT speculation guards for operations assumed side-effect-free, asking whether a prototype could supply indexed accessors [E3](https://bugbountylibrary.com/r/p0%3ACVE-2019-11707.md).
- Traced an in-the-wild sample to an escape-analysis/materialization interaction [E4](https://bugbountylibrary.com/r/p0%3ACVE-2022-1364.md).
- Treated map transition/deprecation code as historically bug-prone and audited predicates against flag combinations [E5](https://bugbountylibrary.com/r/p0%3ACVE-2020-16009.md).

## Variants seen
- Mutable HeapNumber stored as deopt literal, shared mutable box [E1](https://bugbountylibrary.com/r/blog%3Axbow-com-labs-research-zero-to-calc-in-six-days-inside-xbow-chrome-full-chain.md).
- Type check skipped after reassignment to a different type [E2](https://bugbountylibrary.com/r/p0%3ACVE-2022-41128.md).
- Builtin assumed side-effect-free despite prototype accessors [E3](https://bugbountylibrary.com/r/p0%3ACVE-2019-11707.md).
- Dematerialized object with live backing store, double materialization [E4](https://bugbountylibrary.com/r/p0%3ACVE-2022-1364.md).
- Map deprecation without code dependency under pointer compression [E5](https://bugbountylibrary.com/r/p0%3ACVE-2020-16009.md).

## Impact and severity
Each yields type confusion, then relative and arbitrary read/write, then code execution via fake vtable or shellcode [E2](https://bugbountylibrary.com/r/p0%3ACVE-2022-41128.md)[E3](https://bugbountylibrary.com/r/p0%3ACVE-2019-11707.md)[E5](https://bugbountylibrary.com/r/p0%3ACVE-2020-16009.md). Severity rises when chained: renderer RCE plus sandbox escape [E3](https://bugbountylibrary.com/r/p0%3ACVE-2019-11707.md), or three stages reaching unsandboxed execution [E1](https://bugbountylibrary.com/r/blog%3Axbow-com-labs-research-zero-to-calc-in-six-days-inside-xbow-chrome-full-chain.md). One report was paid at 250000 [E1](https://bugbountylibrary.com/r/blog%3Axbow-com-labs-research-zero-to-calc-in-six-days-inside-xbow-chrome-full-chain.md).

## Seen in real software
Open-source packages and projects, and products, where this pattern was found. If the target runs one, compare the version it runs with the fix.
- **Internet Explorer** (JScript9 engine (jscript9.dll), GlobOpt::OptArraySrc) Windows 7 through 11 and Windows Server 2008 through 2022, p, fixed in Windows 7 through 11 and Windows Server 2008 through 2022 wi: CVE-2022-41128: Type confusion in Internet Explorer's JScript9 engine (CVE-2022-41128). Report: https://bugbountylibrary.com/r/p0%3ACVE-2022-41128.md
- **Google Chrome** (V8 JavaScript engine) 100.0.4896.79 and previous, fixed in 100.0.4896.127: CVE-2022-1364: Inconsistent Object Materialization in V8 (CVE-2022-1364). Report: https://bugbountylibrary.com/r/p0%3ACVE-2022-1364.md
- **Google Chrome** (V8 Turbofan Map transition/deprecation logic) 86.0.4240.111 and previous, fixed in 86.0.4240.183: CVE-2020-16009: Chrome Turbofan Type Confusion after Map Deprecation (CVE-2020-16009). Report: https://bugbountylibrary.com/r/p0%3ACVE-2020-16009.md
- **Mozilla Firefox** (IonMonkey JIT compiler) Firefox 67.0.2, likely earlier versions, fixed in Firefox 67.0.3 and Firefox ESR 60.7.1: CVE-2019-11707: IonMonkey Type Confusion in Array.Pop (CVE-2019-11707). Report: https://bugbountylibrary.com/r/p0%3ACVE-2019-11707.md

## Evidence
- E1: https://bugbountylibrary.com/r/blog%3Axbow-com-labs-research-zero-to-calc-in-six-days-inside-xbow-chrome-full-chain.md
- E2: https://bugbountylibrary.com/r/p0%3ACVE-2022-41128.md
- E3: https://bugbountylibrary.com/r/p0%3ACVE-2019-11707.md
- E4: https://bugbountylibrary.com/r/p0%3ACVE-2022-1364.md
- E5: https://bugbountylibrary.com/r/p0%3ACVE-2020-16009.md
