Sep 3, 2026·6 min read·24 visits
A use-after-free in Mozilla's SpiderMonkey engine allows unauthenticated attackers to perform a 1-bit memory corruption, altering bytecode to achieve an out-of-bounds read/write primitive.
A critical use-after-free vulnerability exists in the SpiderMonkey JavaScript engine of Mozilla Firefox and Thunderbird. The flaw occurs when a generator object containing an active for-in loop is garbage-collected before the loop's iterator scope is finalized. This leaves a dangling pointer in the compartment's active enumerators list, allowing attackers to corrupt memory and execute arbitrary code.
CVE-2026-2763 is a critical use-after-free (UAF) vulnerability inside the garbage collection and iteration management subsystems of SpiderMonkey, the JavaScript engine powering Mozilla Firefox and Thunderbird.
The issue stems from a structural mismatch between the lifecycles of JavaScript Generators and standard for-in loop iterators. Under normal conditions, an active iterator is tightly bound to its execution frame and is unlinked when the scope exits.
However, when a loop is paused by a yield statement inside a generator, the engine suspends execution while keeping the iterator active in memory. If the generator is garbage-collected before resumption, the underlying iterator is freed. The compartment list retains a reference to this deallocated memory, leading to a classic dangling pointer scenario.
Because this vulnerability resides inside the core JS engine, it can be triggered remotely without authentication. An attacker can exploit this issue by delivering a malicious webpage that executes crafted JavaScript, compromising the host browser process.
To manage the execution of a for-in loop, the SpiderMonkey engine maintains a doubly-linked list of active enumerators within each execution compartment.
When a loop starts, the interpreter issues a JSOP::Iter bytecode instruction. This invokes the internal ValueToIterator routine, which allocates a PropertyIteratorObject and registers its corresponding NativeIterator block in the global active list via RegisterEnumerator.
When the loop naturally terminates or is aborted by a break statement, the compiler generates a JSOP::EndIter instruction. This instruction executes CloseIterator, which unlinks the iterator from the active compartment list and safely reclaims its structures. The active enumerators list is therefore kept free of inactive or dead iterator records during standard execution flows.
If the loop runs inside a JavaScript Generator, the generator can suspend execution at a yield boundary. When the generator yields, control leaves the frame without exiting the loop scope, meaning CloseIterator is not executed. If the parent execution context then abandons all references to the generator, the garbage collector identifies the generator and its frame stack as dead memory and sweeps them during the next GC cycle. While the PropertyIteratorObject wrapper is finalized, the raw NativeIterator structure is not unlinked from the compartment's active list, resulting in a use-after-free state.
To prevent the dangling pointer, the patch implements strict tracking of active iterators within suspended generator frames, ensuring they are systematically unlinked when the generator itself is destroyed or garbage-collected. The vulnerability resides in how generator garbage collection previously ignored unlinking raw NativeIterator pointers.
Below is a representation of how the fix is integrated into the generator object finalization process. The revised logic ensures that the active iterator is invalidated before the associated memory space is swept by the allocator.
// Vulnerable Flow in value representation:
// When GC occurs, the PropertyIteratorObject is swept but ni->unlink() is never called.
// Patched Flow:
// The engine ensures that active iterators are unlinked when a generator is finalized.
void JSGeneratorObject::finalize(JSFreeOp* fop, JSObject* obj) {
JSGeneratorObject* gen = &obj->as<JSGeneratorObject>();
if (gen->isSuspended()) {
// Unlink all active iterators bound to the suspended frame
UnlinkActiveIteratorsInFrame(fop, gen->getStackFrame());
}
}This modification closes the escape path by linking generator object destruction directly with iterator registration lifecycles. By ensuring that any associated iteration contexts are closed during finalization, the dangling reference is completely avoided. Security audits confirm that this fix covers all variant generator states including early termination and exceptional aborts.
The exploitation process hinges on turning the deallocated NativeIterator memory into a highly controlled write primitive. Because the target object is allocated in js::MallocArena rather than the standard GC heap, an attacker must spray structures of comparable size inside the same allocator. The ideal candidate is ImmutableScriptData, which holds compiled JavaScript bytecode and constants.
When a property deletion occurs later on any object in the compartment, the engine invokes SuppressDeletedPropertyHelper. This function walks the active enumerators list and encounters the dangling pointer. When it attempts to modify the deleted property using cursor->markDeleted(), it performs a bitwise-OR operation on a specific bit inside the memory space now occupied by ImmutableScriptData.
This bit corruption targets the operand of the JSOP::InitElemArray bytecode instruction. In array initialization, this instruction retrieves a 32-bit index representing the initialized length. Corrupting this index value forces the engine to call setDenseInitializedLength with an excessively high value. This extends the logical boundary of the array far beyond its physically allocated buffer size, creating a direct out-of-bounds read and write primitive.
The security impact of CVE-2026-2763 is critical, as it provides a reliable vector for remote code execution (RCE) in user-space applications. By obtaining an out-of-bounds read and write primitive inside the SpiderMonkey JS engine, an attacker bypasses standard web security boundaries and gains full access to the browser's process memory space.
Once the out-of-bounds primitive is established, the attacker can locate adjacent JIT-compiled code blocks, corrupt function pointers, or modify memory structures to execute shellcode. This bypasses address space layout randomization (ASLR) and control flow integrity (CFI) protections built into the platform.
This vulnerability has been assigned a CVSS score of 9.8, indicating maximum severity. It requires no user interaction or elevated privileges to execute, making it highly attractive for chaining with local privilege escalation vulnerabilities to fully compromise the target operating system. While it is not currently recorded in the CISA KEV catalog, its high reliability makes it a critical patching priority.
Remediation requires updating all affected browser and mail client installations immediately. The vulnerability has been addressed in Mozilla Firefox 148, Firefox ESR 115.33, Firefox ESR 140.8, Thunderbird 148, and Thunderbird ESR 140.8. Upgrading to these versions ensures the patch is enforced across all endpoints.
For systems where immediate updates are not possible, administrators should consider temporary mitigation steps to reduce the exposure surface. Restricting the execution of untrusted external JavaScript payloads is highly recommended. Implementing high-security browser configurations that disable non-essential compiler options can also reduce the likelihood of successful exploitation.
Additionally, employing sandbox containerization around the browser processes limits the post-exploitation capabilities of an attacker. Preventing a compromise of the browser process from translating into a complete host takeover reduces the severity of potential active exploitation campaigns in corporate environments.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
Firefox Mozilla | < 148 | 148 |
Firefox ESR Mozilla | < 115.33 | 115.33 |
Firefox ESR Mozilla | < 140.8 | 140.8 |
Thunderbird Mozilla | < 148 | 148 |
Thunderbird ESR Mozilla | < 140.8 | 140.8 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-416 |
| Attack Vector | Network (Unauthenticated) |
| CVSS v3.1 Score | 9.8 |
| EPSS Score | 0.00469 |
| Exploit Status | Proof-of-Concept |
| CISA KEV Status | Not Listed |
Referencing memory after it has been freed, which can lead to program crashes, data corruption, or execution of arbitrary code.
A path traversal vulnerability (CWE-22) in Contao CMS allows unauthenticated remote attackers to bypass directory boundary restrictions in ImagesController and access files within the project directory.
Contao Open Source CMS versions 4.0.0 through 5.3.49 and 5.4.0-RC1 through 5.7.11 contain a Cross-Site Request Forgery (CSRF) vulnerability in backend parameter handling. The `RequestTokenListener` component validates anti-CSRF tokens solely for HTTP POST requests, while GET-based declarative guards run only when an `act` parameter is present in the query string. Consequently, custom backend actions dispatched via alternative parameters such as `key=` can execute without CSRF token verification when triggered by an authenticated user.
Contao CMS versions 4.1.0 through 5.3.49 and 5.4.0-RC1 through 5.7.11 fail to validate form submission tokens and enforce rate limiting when processing activation email resend requests via HTTP POST, enabling resource exhaustion and account state enumeration.
An information disclosure vulnerability in Contao CMS allows unauthenticated site visitors to view protected page titles, URLs, and text excerpts through search queries when protected page indexing is disabled after previously being enabled.
In Vikunja prior to version 2.6.0, relation creation via the CalDAV endpoint fails to invoke the TaskRelation.CanCreate authorization check. This missing access control allows an authenticated user to establish unauthorized relationships and perform write operations against any task, provided its unique identifier (UID) is known.
A cross-project information disclosure vulnerability in Vikunja allows authenticated users with read access to one project to view private task details from unauthorized projects via subtask expansion parameters.