VYPR
High severityNVD Advisory· Published Dec 9, 2025· Updated Dec 9, 2025

Wasmi's Linear Memory has a Critical Use After Free Vulnerability

CVE-2025-66627

Description

Wasmi is a WebAssembly interpreter focused on constrained and embedded systems. In versions 0.41.0, 0.41.1, 0.42.0 through 0.47.1, 0.50.0 through 0.51.2 and 1.0.0, Wasmi's linear memory implementation leads to a Use After Free vulnerability, triggered by a WebAssembly module under certain memory growth conditions. This issue potentially leads to memory corruption, information disclosure, or code execution. This issue is fixed in versions 0.41.2, 0.47.1, 0.51.3 and 1.0.1. To workaround this issue, consider limiting the maximum linear memory sizes where feasible.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

A use-after-free vulnerability in Wasmi's linear memory implementation allows memory corruption, information disclosure, or code execution via crafted WebAssembly modules.

Vulnerability

A use-after-free vulnerability exists in Wasmi, a WebAssembly interpreter focused on constrained and embedded systems, affecting versions 0.41.0 to 1.0.0 [1][4]. The bug resides in the ByteBuffer::grow method of Wasmi's linear memory implementation. When memory growth occurs, the get_vec function returns a Vec that, upon being dropped, frees the underlying buffer, while the ByteBuffer still holds pointers to the freed memory, leading to a use-after-free condition [3].

Exploitation

An attacker can trigger this vulnerability by supplying a specially crafting a WebAssembly module that causes specific memory growth operations [1][4]. No authentication is required, as the module can be loaded by any application using the vulnerable Wasmi interpreter. The attack surface is limited to systems running Wasmi versions in the affected range, which includes many embedded and constrained environments where Wasmi is used.

Impact

Successful exploitation can lead to memory corruption, information disclosure, or arbitrary code execution [1][4]. The advisory rates the impact as high across confidentiality, integrity, and availability, as an attacker could read arbitrary memory, corrupt memory for further attacks, or crash the interpreter [4].

Mitigation

Patches are available in Wasmi versions 0.41.2, 0.47.1, 0.51.3, and 1.0.1 [1][4]. The fix involves wrapping the Vec in ManuallyDrop to prevent premature deallocation [3]. As a workaround, limiting maximum linear memory sizes can reduce exposure where patching is not immediately feasible [1][4].

AI Insight generated on May 19, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
wasmicrates.io
>= 0.41.0, < 0.41.20.41.2
wasmicrates.io
>= 0.42.0, < 0.47.10.47.1
wasmicrates.io
>= 0.50.0, < 0.51.30.51.3
wasmicrates.io
>= 1.0.0, < 1.0.11.0.1

Affected products

2
  • Wasmi/Wasmillm-create
    Range: >=0.41.0 <=0.41.1, >=0.42.0 <=0.47.1, >=0.50.0 <=0.51.2, =1.0.0
  • wasmi-labs/wasmiv5
    Range: >= 0.41.0, < 0.41.2

Patches

1
0e6f0d2a8325

fix bug in ByteBuffer::grow

https://github.com/wasmi-labs/wasmiRobin FreylerDec 5, 2025via ghsa
1 file changed · +14 5
  • crates/core/src/memory/buffer.rs+14 5 modified
    @@ -130,14 +130,18 @@ impl ByteBuffer {
         }
     
         /// Grow the byte buffer to the given `new_size` when backed by a [`Vec`].
    -    fn grow_vec(&mut self, mut vec: Vec<u8>, new_size: usize) -> Result<(), MemoryError> {
    +    fn grow_vec(
    +        &mut self,
    +        mut vec: ManuallyDrop<Vec<u8>>,
    +        new_size: usize,
    +    ) -> Result<(), MemoryError> {
             debug_assert!(vec.len() <= new_size);
             let additional = new_size - vec.len();
             if vec.try_reserve(additional).is_err() {
                 return Err(MemoryError::OutOfSystemMemory);
             };
             vec.resize(new_size, 0x00_u8);
    -        (self.ptr, self.len, self.capacity) = vec_into_raw_parts(vec);
    +        (self.ptr, self.len, self.capacity) = vec_into_raw_parts(ManuallyDrop::into_inner(vec));
             Ok(())
         }
     
    @@ -181,16 +185,21 @@ impl ByteBuffer {
         ///
         /// # Note
         ///
    -    /// The returned `Vec` will free its memory and thus the memory of the [`ByteBuffer`] if dropped.
    -    fn get_vec(&mut self) -> Option<Vec<u8>> {
    +    /// - The returned `Vec` will free its memory and thus the memory of the [`ByteBuffer`] if dropped.
    +    /// - The returned `Vec` is returned as [`ManuallyDrop`] to prevent its buffer from being freed
    +    ///   automatically upon going out of scope.
    +    fn get_vec(&mut self) -> Option<ManuallyDrop<Vec<u8>>> {
             if self.is_static {
                 return None;
             }
             // Safety
             //
             // - At this point we are guaranteed that the byte buffer is backed by a `Vec`
             //   so it is safe to reconstruct the `Vec` by its raw parts.
    -        Some(unsafe { Vec::from_raw_parts(self.ptr, self.len, self.capacity) })
    +        // - The returned `Vec` is returned as [`ManuallyDrop`] to prevent its buffer from being free
    +        //   upon going out of scope.
    +        let vec = unsafe { Vec::from_raw_parts(self.ptr, self.len, self.capacity) };
    +        Some(ManuallyDrop::new(vec))
         }
     }
     
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

4

News mentions

0

No linked articles in our index yet.