CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-104855

CVE-2026-104855: Sandbox Escape via Reentrant State Desynchronization in Wasmtime Bulk Memory Operations

Amit Schendel
Amit Schendel
Senior Security Researcher

Oct 3, 2026·7 min read·14 visits

Executive Summary (TL;DR)

A state desynchronization flaw in Wasmtime's bulk operations allowed host reentrancy during loop preemption checks. Under specific configurations, a callback could modify the linear memory layout or garbage-collection heap, causing the resumed loop to perform use-after-free operations or out-of-bounds writes, potentially leading to WebAssembly sandbox escape.

CVE-2026-104855 is a critical vulnerability involving a race condition and reentrant state desynchronization within Wasmtime, a standalone WebAssembly runtime. Due to incremental mid-operation preemption points in compiler-generated loops for bulk memory and table operations, a host-defined epoch or fuel deadline callback could mutate the WebAssembly Store. Upon resuming, the virtual machine utilized stale cached pointers, resulting in use-after-free, out-of-bounds writes, and sandbox escape.

Vulnerability Overview

The affected component is the Cranelift compiler within Wasmtime, specifically the logic responsible for translating bulk operations such as memory.copy, table.grow, and array.copy into target-specific machine instructions. WebAssembly bulk operations are inherently expensive because they process large contiguous buffers or table structures in a single logical instruction. In multi-tenant environments, executing these instructions monolithically could block the execution thread, circumventing scheduling constraints and deadline mechanisms. To prevent thread monopolization, Wasmtime's compiler partitioned these bulk operations into chunked loops interspersed with preemption points.

These preemption points were designed to check current fuel levels and epoch-based deadlines. When an epoch expired or fuel was exhausted, control returned to the host embedder via a user-defined callback. This architecture created an unexpected reentrancy vector where the host application could execute arbitrary code, modify VM state, or trigger garbage collection before yielding execution back to the guest. Consequently, the assumption of atomic execution during bulk operations was violated.

The security boundary breached is the WebAssembly sandbox itself. WebAssembly relies on strict memory isolation and type safety to guarantee that guest code cannot access host memory or other guest instances. By allowing the host to mutate internal store structures mid-operation, the compiler's assumptions about pointer validity were invalidated, converting safe WebAssembly operations into native memory corruption vulnerabilities.

Root Cause Analysis

The underlying bug is classified as a concurrent execution synchronization issue, mapping specifically to CWE-362 (Race Condition) and CWE-825 (Expired Pointer Dereference). The root cause lies in how the Cranelift compiler optimized bulk memory operations by caching native pointers. Before entering a chunked loop (such as one executing a memory.copy instruction), the compiled machine code resolved the base address of the WebAssembly linear memory and stored it in a CPU register or a stack slot to avoid the overhead of resolving it on every iteration.

If the cooperative preemption check triggered during an iteration, the WebAssembly virtual machine suspended execution and invoked the host-defined Store::epoch_deadline_callback. Because the callback is fully custom, it could perform actions that modified the layout of the WebAssembly store. For instance, the host could call memory.grow, which often forces Wasmtime to reallocate the linear memory buffer to a new virtual memory address, freeing the previous memory space.

Once the host callback completed and returned execution to the guest, the compiled loop resumed at the next chunk boundary. However, the machine code did not re-evaluate or re-resolve the base pointer of the linear memory. Instead, it continued writing data using the stale, cached base pointer that now pointed to deallocated native memory. This state desynchronization bypassed the bounds checks enforced at the start of the instruction, yielding a classic use-after-free or out-of-bounds write primitive.

Code Analysis and Vulnerable Code Paths

Within crates/cranelift/src/func_environ.rs, the Cranelift compiler managed the compilation of bulk memory operations through helper functions like raw_bulk_memory_operation and manual fuel check injection functions. The compiler would insert a manual_fuel_check or an epoch_check inside loop headers generated for bulk instructions. These checks called back into the runtime when thresholds were crossed, leaving the execution state partially suspended while waiting for the host to handle the yield.

// Vulnerable compiler logic that inserted mid-operation checks:
fn manual_fuel_check(&mut self, builder: &mut FunctionBuilder<'_>, fuel_to_consume: ir::Value) {
    self.fuel_increment_var(builder);
 
    let fuel = builder.use_var(self.fuel_var);
    let fuel = builder.ins().iadd(fuel, fuel_to_consume);
    builder.def_var(self.fuel_var, fuel);
 
    self.fuel_check(builder);
}

The compiled loop structure can be conceptualized using the following diagram, showing how the preemption check breaks the assumption of atomicity.

Additionally, in table.grow operations, Wasmtime temporarily populated newly allocated slots with null references before completing the fill process with target initialization references. If preemption occurred mid-loop and the host decided to abort execution or trap, the table remained in an intermediate, partially initialized state. Because non-nullable tables enforce the invariant that references must never be null, subsequent operations on these tables assumed type safety, leading to type confusion and native segmentation faults when dereferencing the unexpected null values.

Exploitation Methodology & Reentrancy Vectors

To trigger this vulnerability, an attacker must first be able to execute arbitrary WebAssembly payloads on a host that implements cooperative preemption via epoch-based deadlines or fuel metering. The host application must also configure a reentrant or state-modifying callback. In a typical exploitation scenario, the attacker crafts a WebAssembly module containing a large memory.copy or array.copy operation designed to cross multiple chunk boundaries and force a preemption event.

The timing of the preemption is critical. If the host uses epoch-based deadlines, the background epoch thread must increment the epoch precisely while the bulk operation loop is executing. Once the loop triggers the preemption, control flows to the host callback. Inside this callback, the attacker-controlled host environment or a misconfigured handler triggers a memory reallocation event (e.g., calling memory.grow from a concurrent thread or within the reentrant context) or initiates a garbage collection cycle.

During garbage collection, reference-typed pointers on the GC heap are compacted and moved to optimize memory layout. When the callback finishes and the VM resumes the chunked loop, the stored references inside the CPU registers are now pointing to invalid memory. The resumed copy operation then writes guest-controlled data directly to these obsolete addresses, giving the attacker a powerful read-and-write primitive over the host process's virtual address space.

Impact Assessment & Sandbox Escape Mechanics

The security impact of CVE-2026-104855 is severe, as it directly undermines the core safety guarantees of the WebAssembly execution model. Although the CVSS score is computed as 2.0 (Low) due to the high complexity and the requirement for specific host configurations, the real-world impact in vulnerable configurations is a complete sandbox escape. An attacker with the ability to write to arbitrary native memory locations can overwrite host execution pointers, such as function pointers or return addresses on the stack.

By corrupting the host process's memory space, the guest code can transition from restricted WebAssembly instructions to executing arbitrary native code on the host process. This allows the attacker to inherit the full permissions of the host process, potentially leading to unauthorized data access, local privilege escalation, or lateral movement within the hosting network.

Furthermore, because this flaw corrupts the underlying memory allocator and GC structures, it can cause unstable VM states that manifest as intermittent native crashes. In multi-tenant environments, such as cloud-native edge computing platforms or serverless database extensions, this vulnerability could allow one tenant to read or modify the state of other tenants sharing the same host process.

Remediation & Patch Verification

The vulnerability has been addressed by removing the incremental preemption checks inside bulk operation loops. In commits 3ebfbe5af4927c157d6fcaca42b8dbb6d17b73fb (v47.0.3) and 99b0bc39d447317a4102c056081c83a9a84a46e0 (v46.0.2), the Cranelift compiler was refactored to perform a single, atomic preemption check before commencing the bulk memory operation. This upfront validation calculates the total fuel cost of the operation and verifies the epoch deadline before any data transfer begins.

// Patched compiler code implementing upfront checks:
fn pre_translate_bulk_op(
    &mut self,
    builder: &mut FunctionBuilder,
    cost: ir::Value,
) -> WasmResult<()> {
    let const_cost =
        Self::value_as_const_int(builder, cost).map(|c| i64::try_from(c).unwrap_or(i64::MAX));
 
    if self.tunables.consume_fuel {
        // Fold constant costs or dynamically increment fuel up front
        // ...
    }
 
    const SMALL_BULK_OP_COST: i64 = 128;
    if let Some(cost) = const_cost && cost <= SMALL_BULK_OP_COST {
        return Ok(());
    }
 
    self.translate_loop_header(builder)
}

By transitioning to atomic checks, the compiled code guarantees that once a bulk memory operation starts, it executes to completion without yielding back to the host. This eliminates the reentrancy vector entirely. To verify the completeness of the fix, security teams should ensure that all instances of Wasmtime are upgraded to version 46.0.2, 47.0.3, or higher, and verify that any custom resource limiters are configured to prevent thread-blocking abuse from large, non-preemptible bulk operations.

Official Patches

bytecodeallianceGitHub Security Advisory
bytecodeallianceWasmtime Main Fix Commit

Fix Analysis (3)

Technical Appendix

CVSS Score
2.0/ 10
CVSS:4.0/AV:N/AC:H/AT:P/PR:H/UI:P/VC:N/VI:L/VA:L/SC:N/SI:N/SA:N

Affected Systems

Wasmtime standalone WebAssembly runtime

Affected Versions Detail

Product
Affected Versions
Fixed Version
Wasmtime
Bytecode Alliance
>= 46.0.0, < 46.0.246.0.2
Wasmtime
Bytecode Alliance
>= 47.0.0, < 47.0.347.0.3
AttributeDetail
CWE IDCWE-362 (Concurrent Execution using Shared Resource with Improper Synchronization)
Attack VectorNetwork / Local
CVSS Score2.0 (Low Base / Critical Downstream Impact)
EPSS ScoreNot Listed
ImpactSandbox Escape, Memory Corruption (Use-After-Free, Out-of-Bounds Write)
Exploit StatusProof-of-Concept
KEV StatusNot Listed

MITRE ATT&CK Mapping

T1068Exploitation for Privilege Escalation
Privilege Escalation
CWE-362
Concurrent Execution using Shared Resource with Improper Synchronization ('Race Condition')

The software performs multiple concurrent operations on a shared resource, but does not properly synchronize access, leading to unexpected behaviors or race conditions.

Vulnerability Timeline

Wasmtime developers backport patches and release fixed versions 46.0.2 and 47.0.3
2026-07-31
GitHub Advisory GHSA-2hw9-mc66-jc2q published and CVE-2026-104855 assigned
2026-10-02

References & Sources

  • [1]GHSA-2hw9-mc66-jc2q
  • [2]CVE-2026-104855 Record

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•about 23 hours ago•CVE-2026-107844
5.3

CVE-2026-107844: Path Traversal Vulnerability in Contao ImagesController

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.

Amit Schendel
Amit Schendel
8 views•5 min read
•1 day ago•CVE-2026-107848
3.5

CVE-2026-107848: Cross-Site Request Forgery (CSRF) in Contao Backend Actions via GET Requests

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.

Amit Schendel
Amit Schendel
7 views•5 min read
•1 day ago•CVE-2026-107843
5.3

CVE-2026-107843: Unthrottled Activation Email Resend and Account Enumeration in Contao CMS

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.

Amit Schendel
Amit Schendel
8 views•4 min read
•1 day ago•CVE-2026-107842
5.3

CVE-2026-107842: Information Disclosure via Stale Indexing in Contao Search Module

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.

Amit Schendel
Amit Schendel
10 views•4 min read
•1 day ago•GHSA-G38J-7V97-X298
6.5

GHSA-G38J-7V97-X298: Missing Authorization Check in Vikunja CalDAV Task Relation Creation

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.

Alon Barad
Alon Barad
12 views•5 min read
•1 day ago•GHSA-3HC7-R24J-RPWC
6.8

GHSA-3hc7-r24j-rpwc: Cross-Project Task Disclosure via Subtask Expansion in Vikunja

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.

Alon Barad
Alon Barad
9 views•5 min read