CVE-2026-119332 in Ladybird
Summary
by MITRE • 10/30/2026
Ladybird is a truly independent web browser. Prior to 209579c96473c75bd5eba9701fcadb841a045964, FinalizationRegistry::cleanup() in Libraries/LibJS/Runtime/FinalizationRegistry.cpp removed a dead record from m_records, retained an iterator to the next FinalizationRecord, and then invoked attacker-controlled JavaScript through the cleanup callback. If that callback called unregister() for the next record, remove_by_token() freed the node referenced by the retained iterator, and the next cleanup iteration read its target and held_value fields after free. This reliably crashes instrumented WebContent builds and creates a memory-corruption primitive in production builds. This vulnerability is fixed by commit 209579c96473c75bd5eba9701fcadb841a045964.
If you want to get best quality of vulnerability data, you may have to visit VulDB.
Analysis
by VulDB Data Team • 10/31/2026
The Ladybird web browser, an independent project aiming to provide a modern browsing experience, contains a critical memory safety vulnerability within its JavaScript engine's garbage collection finalization logic. This flaw resides specifically in the FinalizationRegistry::cleanup() function located in Libraries/LibJS/Runtime/FinalizationRegistry.cpp. The issue arises from improper handling of iterator validity during the cleanup process for registered objects that are subject to garbage collection. In web browsers, the JavaScript engine must manage complex lifecycles where native C++ objects and JavaScript values interact closely. When an object is finalized, a callback function provided by the developer or attacker can be executed. The vulnerability stems from how Ladybird manages its internal list of finalization records while executing these callbacks.
The technical flaw involves a use-after-free condition triggered during the iteration over FinalizationRecord structures. Prior to the fix commit 209579c96473c75bd5eba9701fcadb841a045964, the cleanup function would remove a dead record from its internal container of records, m_records. Crucially, it retained an iterator pointing to the next FinalizationRecord in the sequence before invoking the attacker-controlled JavaScript callback associated with the current record. This design choice assumes that removing one element will not invalidate iterators or pointers to adjacent elements, which is true for some data structures but dangerous if subsequent operations modify those adjacent elements.
When the cleanup callback executes, it operates within an environment controlled by malicious JavaScript code crafted specifically to exploit this race condition in logic flow. If the attacker's script invokes the unregister() method on a FinalizationRecord that corresponds to the next record referenced by the retained iterator, the internal data structure is modified again. Specifically, remove_by_token() frees the memory node associated with that next record while the cleanup loop still holds an active iterator pointing directly into that now-freed memory region. This creates a classic use-after-free scenario where the program continues execution using stale pointers to deallocated heap memory.
The operational impact of this vulnerability is severe and varies depending on the build configuration of Ladybird. In instrumented builds, such as those with AddressSanitizer or similar debugging tools enabled, this corruption reliably causes immediate crashes due to memory access violations detected by the instrumentation layers. This makes the bug easily reproducible for developers but potentially less obvious in production environments where these safety checks are disabled. In production builds without aggressive memory protection mechanisms, the use-after-free creates a potent memory-corruption primitive. An attacker could potentially leverage this state corruption to achieve arbitrary code execution or cause denial of service by corrupting heap metadata and adjacent object structures during subsequent allocations.
This vulnerability aligns with CWE-416, Use After Free, which describes situations where a program continues to use a pointer after it has been freed, leading to undefined behavior. From an offensive security perspective, this technique maps to MITRE ATT&CK techniques related to memory corruption and potentially code execution via JavaScript-based attacks in browser contexts. The specific mechanism of exploiting garbage collection callbacks is reminiscent of advanced exploitation strategies seen in other major browsers where finalization hooks are abused to manipulate heap layouts or bypass sandbox boundaries.
Mitigation for this issue has been addressed through the referenced commit which corrects the iterator management logic within FinalizationRegistry::cleanup(). Developers and users should ensure they are running versions of Ladybird that include this fix, as earlier builds remain vulnerable to exploitation via crafted JavaScript pages containing specific unregister calls during finalization callbacks. For security researchers analyzing similar implementations in other browsers or engines, it is critical to verify that iterators over container elements are not retained across callback invocations that may modify the same container structure. Ensuring iterator validity after any operation that might alter the underlying collection's memory layout is essential for preventing use-after-free vulnerabilities in garbage-collected systems.