# GC-untracked live object freed

Live objects reachable only via callbacks, fibers, ephemerons or plugin fields that the collector fails to mark

_Area: Memory corruption and native code. Seen in 7 disclosed reports; 2 confirmed bounties: $300 and $800; latest 2021-12-13. Updated 2026-10-23._

## How it works
A garbage collector frees an object only if it cannot reach it from roots. The bug is a reachability gap: some reference path is invisible to the collector, so a still-live object looks dead and is reclaimed. The assumption that breaks is "every reference the program can still use is one the collector can see." Common gaps: a callback or fiber holds a reference the runtime does not scan, an ephemeron (WeakMap) marking pass exits before re-checking entries that just became reachable, or a compiler pass changes a stored value's type after a safety decision (like WriteBarrier elision) was already made for the old type [E1](https://bugbountylibrary.com/r/p0%3ACVE-2021-4102.md)[E2](https://bugbountylibrary.com/r/p0%3ACVE-2021-37975.md)[E3](https://bugbountylibrary.com/r/p0%3ACVE-2019-1367.md)[E6](https://bugbountylibrary.com/r/h1%3A215854.md).

## Where it shows up
- Raw native pointers to script objects in plugin/binding code (e.g. `JSC::JSObject*` members) with no GC tracking [E4](https://bugbountylibrary.com/r/p0%3ACVE-2021-1879.md)
- Callbacks that receive `arguments`/`this` and run user code (sort comparators, prototype hooks) [E3](https://bugbountylibrary.com/r/p0%3ACVE-2019-1367.md)
- Fibers that yield objects created inside them (Procs, closures) [E6](https://bugbountylibrary.com/r/h1%3A215854.md)
- Ephemeron/WeakMap marking loops that can exit while the worklist still grows [E2](https://bugbountylibrary.com/r/p0%3ACVE-2021-37975.md)
- Compiler passes that elide barriers or change representations after lowering [E1](https://bugbountylibrary.com/r/p0%3ACVE-2021-4102.md)
- FIXME/TODO comments questioning GC lifetime of a pointer [E4](https://bugbountylibrary.com/r/p0%3ACVE-2021-1879.md)
- GC mark code that dereferences a value without checking its type tag [E5](https://bugbountylibrary.com/r/h1%3A208526.md)

## How to review
The invariant: any object the program can still reach must be reachable through a path the collector scans. For each reference, ask who owns it and whether the collector knows. Check that every callback/fiber/plugin field holding a script object is registered as a GC root or traced. For ephemeron marking, confirm the loop re-iterates whenever the worklist adds objects that could make previously-unreachable ephemerons live [E2](https://bugbountylibrary.com/r/p0%3ACVE-2021-37975.md). For compiler passes, confirm no later pass can change a stored value's type after a barrier-elision decision [E1](https://bugbountylibrary.com/r/p0%3ACVE-2021-4102.md). For mark code, confirm type tags are validated before dereference [E5](https://bugbountylibrary.com/r/h1%3A208526.md).

## Variants seen
- Barrier elision after type change in JIT [E1](https://bugbountylibrary.com/r/p0%3ACVE-2021-4102.md)
- Ephemeron marking iteration exits early [E2](https://bugbountylibrary.com/r/p0%3ACVE-2021-37975.md)
- Arguments object untracked during callback [E3](https://bugbountylibrary.com/r/p0%3ACVE-2019-1367.md)
- Plugin field untracked by GC [E4](https://bugbountylibrary.com/r/p0%3ACVE-2021-1879.md)
- Malformed input leaves partially-initialized stack value dereferenced in mark phase [E5](https://bugbountylibrary.com/r/h1%3A208526.md)
- Fiber-yielded Proc not marked [E6](https://bugbountylibrary.com/r/h1%3A215854.md)

## Why fixes fail
E6 shows a regression: a previously fixed GC bug was reintroduced by a later commit, so a known issue plus bisect is a fast path. Fixes that patch one callback can leave sibling callbacks with the same gap [E3](https://bugbountylibrary.com/r/p0%3ACVE-2019-1367.md).

## Impact and severity
Use-after-free enabling RCE in browsers [E1](https://bugbountylibrary.com/r/p0%3ACVE-2021-4102.md)[E2](https://bugbountylibrary.com/r/p0%3ACVE-2021-37975.md)[E3](https://bugbountylibrary.com/r/p0%3ACVE-2019-1367.md), universal XSS in Safari [E4](https://bugbountylibrary.com/r/p0%3ACVE-2021-1879.md), and interpreter crashes/aborts in sandboxed mruby [E5](https://bugbountylibrary.com/r/h1%3A208526.md)[E6](https://bugbountylibrary.com/r/h1%3A215854.md). Severity is highest when the freed object is attacker-influenced and the runtime is a security boundary; worse when the bug is reachable from ordinary script.

## Evidence
- E1: https://bugbountylibrary.com/r/p0%3ACVE-2021-4102.md
- E2: https://bugbountylibrary.com/r/p0%3ACVE-2021-37975.md
- E3: https://bugbountylibrary.com/r/p0%3ACVE-2019-1367.md
- E4: https://bugbountylibrary.com/r/p0%3ACVE-2021-1879.md
- E5: https://bugbountylibrary.com/r/h1%3A208526.md
- E6: https://bugbountylibrary.com/r/h1%3A215854.md
