CVE-2025-61670
Wasmtime has memory leak in C API with `externref` and `anyref` types
Wasmtime is a runtime for WebAssembly. Wasmtime 37.0.0 and 37.0.1 have memory leaks in the C/C++ API when using bindings for the anyref or externref WebAssembly values. This is caused by a regression introduced during the development of 37.0.0 and all prior versions of Wasmtime are unaffected. If anyref or externref is not used in the C/C++ API then embeddings are also unaffected by the leaky behavior. The wasmtime Rust crate is unaffected by this leak.
Development of Wasmtime 37.0.0 included a refactoring in Rust of changing the old ManuallyRooted<T> type to a new OwnedRooted<T> type. This change was integrated into Wasmtime's C API but left the C API in a state which had memory leaks. Additionally the new ownership semantics around this type were not reflected into the C++ API, making it leak-prone. A short version of the change is that previously ManuallyRooted<T>, as the name implies, required manual calls to an "unroot" operation. If this was forgotten then the memory was still cleaned up when the wasmtime_store_t itself was destroyed eventually. Documentation of when to "unroot" was sparse and there were already situations prior to 37.0.0 where memory would be leaked until the store was destroyed anyway. All memory, though, was always bound by the store, and destroying the store would guarantee that there were no memory leaks.
In migrating to OwnedRooted<T> the usage of the type in Rust changed. A manual "unroot" operation is no longer required and it happens naturally as a destructor of the OwnedRooted<T> type in Rust itself. These new resource ownership semantics were not fully integrated into the preexisting semantics of the C/C++ APIs in Wasmtime. A crucial distinction of OwnedRooted<T> vs ManuallyRooted<T> is that the OwnedRooted<T> type allocates host memory outside of the store. This means that if an OwnedRooted<T> is leaked then destroying a store does not release this memory and it's a permanent memory leak on the host.
This led to a few distinct, but related, issues arising: A typo in the wasmtime_val_unroot function in the C API meant that it did not actually unroot anything. This meant that even if embedders faithfully call the function then memory will be leaked. If a host-defined function returned a wasmtime_{externref,anyref}_t value then the value was never unrooted. The C/C++ API no longer has access to the value and the Rust implementation did not unroot. This meant that any values returned this way were never unrooted. The goal of the C++ API of Wasmtime is to encode automatic memory management in the type system, but the C++ API was not updated when OwnedRooted<T> was added. This meant that idiomatic usage of the C++ API would leak memory due to a lack of destructors on values.
These issues have all been fixed in a 37.0.2 release of Wasmtime. The implementation of the C and C++ APIs have been updated accordingly and respectively to account for the changes of ownership here. For example wasmtime_val_unroot has been fixed to unroot, the Rust-side implementation of calling an embedder-defined function will unroot return values, and the C++ API now has destructors on the ExternRef, AnyRef, and Val types. These changes have been made to the 37.0.x release branch in a non-API-breaking fashion. Changes to the 38.0.0 release branch (and main in the Wasmtime repository) include minor API updates to better accommodate the API semantic changes. The only known workaround at this time is to avoid using externref and anyref in the C/C++ API of Wasmtime. If avoiding those types is not possible then it's required for users to update to mitigate the leak issue.
Attack profile
How easy it is to exploit
- Attack vector
- Adjacent network
- Complexity
- Low
- Privileges needed
- Low
- User interaction
- Passive
What an attacker can affect
- Confidentiality
- None
- Integrity
- None
- Availability
- Low
Exploit likelihood
What each source reports
CVE List Score used
1.0
Wasmtime has memory leak in C API with `externref` and `anyref` types
Wasmtime is a runtime for WebAssembly. Wasmtime 37.0.0 and 37.0.1 have memory leaks in the C/C++ API when using bindings for the anyref or externref WebAssembly values. This is caused by a regression introduced during the development of 37.0.0 and all prior versions of Wasmtime are unaffected. If anyref or externref is not used in the C/C++ API then embeddings are also unaffected by the leaky behavior. The wasmtime Rust crate is unaffected by this leak.
Development of Wasmtime 37.0.0 included a refactoring in Rust of changing the old ManuallyRooted<T> type to a new OwnedRooted<T> type. This change was integrated into Wasmtime's C API but left the C API in a state which had memory leaks. Additionally the new ownership semantics around this type were not reflected into the C++ API, making it leak-prone. A short version of the change is that previously ManuallyRooted<T>, as the name implies, required manual calls to an "unroot" operation. If this was forgotten then the memory was still cleaned up when the wasmtime_store_t itself was destroyed eventually. Documentation of when to "unroot" was sparse and there were already situations prior to 37.0.0 where memory would be leaked until the store was destroyed anyway. All memory, though, was always bound by the store, and destroying the store would guarantee that there were no memory leaks.
In migrating to OwnedRooted<T> the usage of the type in Rust changed. A manual "unroot" operation is no longer required and it happens naturally as a destructor of the OwnedRooted<T> type in Rust itself. These new resource ownership semantics were not fully integrated into the preexisting semantics of the C/C++ APIs in Wasmtime. A crucial distinction of OwnedRooted<T> vs ManuallyRooted<T> is that the OwnedRooted<T> type allocates host memory outside of the store. This means that if an OwnedRooted<T> is leaked then destroying a store does not release this memory and it's a permanent memory leak on the host.
This led to a few distinct, but related, issues arising: A typo in the wasmtime_val_unroot function in the C API meant that it did not actually unroot anything. This meant that even if embedders faithfully call the function then memory will be leaked. If a host-defined function returned a wasmtime_{externref,anyref}_t value then the value was never unrooted. The C/C++ API no longer has access to the value and the Rust implementation did not unroot. This meant that any values returned this way were never unrooted. The goal of the C++ API of Wasmtime is to encode automatic memory management in the type system, but the C++ API was not updated when OwnedRooted<T> was added. This meant that idiomatic usage of the C++ API would leak memory due to a lack of destructors on values.
These issues have all been fixed in a 37.0.2 release of Wasmtime. The implementation of the C and C++ APIs have been updated accordingly and respectively to account for the changes of ownership here. For example wasmtime_val_unroot has been fixed to unroot, the Rust-side implementation of calling an embedder-defined function will unroot return values, and the C++ API now has destructors on the ExternRef, AnyRef, and Val types. These changes have been made to the 37.0.x release branch in a non-API-breaking fashion. Changes to the 38.0.0 release branch (and main in the Wasmtime repository) include minor API updates to better accommodate the API semantic changes. The only known workaround at this time is to avoid using externref and anyref in the C/C++ API of Wasmtime. If avoiding those types is not possible then it's required for users to update to mitigate the leak issue.
- Record
CVE-2025-61670- CVSS 4.0
- 1.0 Low
CVSS:4.0/AV:A/AC:L/AT:P/PR:L/UI:P/VC:N/VI:N/VA:L/SC:N/SI:N/SA:L - Weakness
- CWE-772
- Updated
- 2026-11-02
EUVDEUVD-2025-33183
1.0
Wasmtime is a runtime for WebAssembly. Wasmtime 37.0.0 and 37.0.1 have memory leaks in the C/C++ API when using bindings for the anyref or externref WebAssembly values. This is caused by a regression introduced during the development of 37.0.0 and all prior versions of Wasmtime are unaffected. If anyref or externref is not used in the C/C++ API then embeddings are also unaffected by the leaky behavior. The wasmtime Rust crate is unaffected by this leak.
Development of Wasmtime 37.0.0 included a refactoring in Rust of changing the old ManuallyRooted<T> type to a new OwnedRooted<T> type. This change was integrated into Wasmtime's C API but left the C API in a state which had memory leaks. Additionally the new ownership semantics around this type were not reflected into the C++ API, making it leak-prone. A short version of the change is that previously ManuallyRooted<T>, as the name implies, required manual calls to an "unroot" operation. If this was forgotten then the memory was still cleaned up when the wasmtime_store_t itself was destroyed eventually. Documentation of when to "unroot" was sparse and there were already situations prior to 37.0.0 where memory would be leaked until the store was destroyed anyway. All memory, though, was always bound by the store, and destroying the store would guarantee that there were no memory leaks.
In migrating to OwnedRooted<T> the usage of the type in Rust changed. A manual "unroot" operation is no longer required and it happens naturally as a destructor of the OwnedRooted<T> type in Rust itself. These new resource ownership semantics were not fully integrated into the preexisting semantics of the C/C++ APIs in Wasmtime. A crucial distinction of OwnedRooted<T> vs ManuallyRooted<T> is that the OwnedRooted<T> type allocates host memory outside of the store. This means that if an OwnedRooted<T> is leaked then destroying a store does not release this memory and it's a permanent memory leak on the host.
This led to a few distinct, but related, issues arising: A typo in the wasmtime_val_unroot function in the C API meant that it did not actually unroot anything. This meant that even if embedders faithfully call the function then memory will be leaked. If a host-defined function returned a wasmtime_{externref,anyref}_t value then the value was never unrooted. The C/C++ API no longer has access to the value and the Rust implementation did not unroot. This meant that any values returned this way were never unrooted. The goal of the C++ API of Wasmtime is to encode automatic memory management in the type system, but the C++ API was not updated when OwnedRooted<T> was added. This meant that idiomatic usage of the C++ API would leak memory due to a lack of destructors on values.
These issues have all been fixed in a 37.0.2 release of Wasmtime. The implementation of the C and C++ APIs have been updated accordingly and respectively to account for the changes of ownership here. For example wasmtime_val_unroot has been fixed to unroot, the Rust-side implementation of calling an embedder-defined function will unroot return values, and the C++ API now has destructors on the ExternRef, AnyRef, and Val types. These changes have been made to the 37.0.x release branch in a non-API-breaking fashion. Changes to the 38.0.0 release branch (and main in the Wasmtime repository) include minor API updates to better accommodate the API semantic changes. The only known workaround at this time is to avoid using externref and anyref in the C/C++ API of Wasmtime. If avoiding those types is not possible then it's required for users to update to mitigate the leak issue.
- Record
EUVD-2025-33183- CVSS 4.0
- 1.0 Low
CVSS:4.0/AV:A/AC:L/AT:P/PR:L/UI:P/VC:N/VI:N/VA:L/SC:N/SI:N/SA:L - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-vvp9-h8p2-xwfc
1.0
Wasmtime: Memory leak in C API with `externref` and `anyref` types
Impact
Wasmtime 37.0.0 and 37.0.1 have memory leaks in the C/C++ API when using bindings for the anyref or externref WebAssembly values. This is caused by a regression introduced during the development of 37.0.0 and all prior versions of Wasmtime are unaffected. If anyref or externref is not used in the C/C++ API then embeddings are also unaffected by the leaky behavior. The wasmtime Rust crate is unaffected by this leak.
Development of Wasmtime 37.0.0 included a refactoring in Rust of changing the old ManuallyRooted<T> type to a new OwnedRooted<T> type. This change was integrated into Wasmtime's C API but left the C API in a state which had memory leaks. Additionally the new ownership semantics around this type were not reflected into the C++ API, making it leak-prone. A short version of the change is that previously ManuallyRooted<T>, as the name implies, required manual calls to an "unroot" operation. If this was forgotten then the memory was still cleaned up when the wasmtime_store_t itself was destroyed eventually. Documentation of when to "unroot" was sparse and there were already situations prior to 37.0.0 where memory would be leaked until the store was destroyed anyway. All memory, though, was always bound by the store, and destroying the store would guarantee that there were no memory leaks.
In migrating to OwnedRooted<T> the usage of the type in Rust changed. A manual "unroot" operation is no longer required and it happens naturally as a destructor of the OwnedRooted<T> type in Rust itself. These new resource ownership semantics were not fully integrated into the preexisting semantics of the C/C++ APIs in Wasmtime. A crucial distinction of OwnedRooted<T> vs ManuallyRooted<T> is that the OwnedRooted<T> type allocates host memory outside of the store. This means that if an OwnedRooted<T> is leaked then destroying a store does not release this memory and it's a permanent memory leak on the host. This led to a few distinct, but related, issues arising:
- A typo in the
wasmtime_val_unrootfunction in the C API meant that it did not actually unroot anything. This meant that even if embedders faithfully call the function then memory will be leaked. - If a host-defined function returned a
wasmtime_{externref,anyref}_tvalue then the value was never unrooted. The C/C++ API no longer has access to the value and the Rust implementation did not unroot. This meant that any values returned this way were never unrooted. - The goal of the C++ API of Wasmtime is to encode automatic memory management in the type system, but the C++ API was not updated when
OwnedRooted<T>was added. This meant that idiomatic usage of the C++ API would leak memory due to a lack of destructors on values.
These issues have all been fixed in a 37.0.2 release of Wasmtime. The implementation of the C and C++ APIs have been updated accordingly and respectively to account for the changes of ownership here. For example wasmtime_val_unroot has been fixed to unroot, the Rust-side implementation of calling an embedder-defined function will unroot return values, and the C++ API now has destructors on the ExternRef, AnyRef, and Val types. These changes have been made to the 37.0.x release branch in a non-API-breaking fashion. Changes to the 38.0.0 release branch (and main in the Wasmtime repository) include minor API updates to better accomodate the API semantic changes.
Patches
Wasmtime 37.0.2 has been released which fixes these issues. Users of 37.0.0 and 37.0.1 are recommended to upgrade. Users of 36.0.x and prior are unaffected and need not upgrade.
Workarounds
The only known workaround at this time is to avoid using externref and anyref in the C/C++ API of Wasmtime. If avoiding those types is not possible then it's required for users to update to mitigate the leak issue.
Remediations
The Wasmtime project will be looking more closely into improving the situation around testing the C…
- Record
GHSA-vvp9-h8p2-xwfc- CVSS 4.0
- 1.0 Low
CVSS:4.0/AV:A/AC:L/AT:P/PR:L/UI:P/VC:N/VI:N/VA:L/SC:N/SI:N/SA:L - CVSS 3.1
- 3.3 Low
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:L - Weakness
- CWE-772
- Updated
- 2026-11-02
NVD
1.0
Wasmtime is a runtime for WebAssembly. Wasmtime 37.0.0 and 37.0.1 have memory leaks in the C/C++ API when using bindings for the anyref or externref WebAssembly values. This is caused by a regression introduced during the development of 37.0.0 and all prior versions of Wasmtime are unaffected. If anyref or externref is not used in the C/C++ API then embeddings are also unaffected by the leaky behavior. The wasmtime Rust crate is unaffected by this leak.
Development of Wasmtime 37.0.0 included a refactoring in Rust of changing the old ManuallyRooted<T> type to a new OwnedRooted<T> type. This change was integrated into Wasmtime's C API but left the C API in a state which had memory leaks. Additionally the new ownership semantics around this type were not reflected into the C++ API, making it leak-prone. A short version of the change is that previously ManuallyRooted<T>, as the name implies, required manual calls to an "unroot" operation. If this was forgotten then the memory was still cleaned up when the wasmtime_store_t itself was destroyed eventually. Documentation of when to "unroot" was sparse and there were already situations prior to 37.0.0 where memory would be leaked until the store was destroyed anyway. All memory, though, was always bound by the store, and destroying the store would guarantee that there were no memory leaks.
In migrating to OwnedRooted<T> the usage of the type in Rust changed. A manual "unroot" operation is no longer required and it happens naturally as a destructor of the OwnedRooted<T> type in Rust itself. These new resource ownership semantics were not fully integrated into the preexisting semantics of the C/C++ APIs in Wasmtime. A crucial distinction of OwnedRooted<T> vs ManuallyRooted<T> is that the OwnedRooted<T> type allocates host memory outside of the store. This means that if an OwnedRooted<T> is leaked then destroying a store does not release this memory and it's a permanent memory leak on the host.
This led to a few distinct, but related, issues arising: A typo in the wasmtime_val_unroot function in the C API meant that it did not actually unroot anything. This meant that even if embedders faithfully call the function then memory will be leaked. If a host-defined function returned a wasmtime_{externref,anyref}_t value then the value was never unrooted. The C/C++ API no longer has access to the value and the Rust implementation did not unroot. This meant that any values returned this way were never unrooted. The goal of the C++ API of Wasmtime is to encode automatic memory management in the type system, but the C++ API was not updated when OwnedRooted<T> was added. This meant that idiomatic usage of the C++ API would leak memory due to a lack of destructors on values.
These issues have all been fixed in a 37.0.2 release of Wasmtime. The implementation of the C and C++ APIs have been updated accordingly and respectively to account for the changes of ownership here. For example wasmtime_val_unroot has been fixed to unroot, the Rust-side implementation of calling an embedder-defined function will unroot return values, and the C++ API now has destructors on the ExternRef, AnyRef, and Val types. These changes have been made to the 37.0.x release branch in a non-API-breaking fashion. Changes to the 38.0.0 release branch (and main in the Wasmtime repository) include minor API updates to better accommodate the API semantic changes. The only known workaround at this time is to avoid using externref and anyref in the C/C++ API of Wasmtime. If avoiding those types is not possible then it's required for users to update to mitigate the leak issue.
- Record
CVE-2025-61670- CVSS 4.0
- 1.0 Low
CVSS:4.0/AV:A/AC:L/AT:P/PR:L/UI:P/VC:N/VI:N/VA:L/SC:N/SI:N/SA:L/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - CVSS 3.1
- 3.3 Low
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:L - Weakness
- CWE-772
- Updated
- 2026-11-02
OSV
1.0
Wasmtime has memory leak in C API with `externref` and `anyref` types
Wasmtime is a runtime for WebAssembly. Wasmtime 37.0.0 and 37.0.1 have memory leaks in the C/C++ API when using bindings for the anyref or externref WebAssembly values. This is caused by a regression introduced during the development of 37.0.0 and all prior versions of Wasmtime are unaffected. If anyref or externref is not used in the C/C++ API then embeddings are also unaffected by the leaky behavior. The wasmtime Rust crate is unaffected by this leak.
Development of Wasmtime 37.0.0 included a refactoring in Rust of changing the old ManuallyRooted<T> type to a new OwnedRooted<T> type. This change was integrated into Wasmtime's C API but left the C API in a state which had memory leaks. Additionally the new ownership semantics around this type were not reflected into the C++ API, making it leak-prone. A short version of the change is that previously ManuallyRooted<T>, as the name implies, required manual calls to an "unroot" operation. If this was forgotten then the memory was still cleaned up when the wasmtime_store_t itself was destroyed eventually. Documentation of when to "unroot" was sparse and there were already situations prior to 37.0.0 where memory would be leaked until the store was destroyed anyway. All memory, though, was always bound by the store, and destroying the store would guarantee that there were no memory leaks.
In migrating to OwnedRooted<T> the usage of the type in Rust changed. A manual "unroot" operation is no longer required and it happens naturally as a destructor of the OwnedRooted<T> type in Rust itself. These new resource ownership semantics were not fully integrated into the preexisting semantics of the C/C++ APIs in Wasmtime. A crucial distinction of OwnedRooted<T> vs ManuallyRooted<T> is that the OwnedRooted<T> type allocates host memory outside of the store. This means that if an OwnedRooted<T> is leaked then destroying a store does not release this memory and it's a permanent memory leak on the host.
This led to a few distinct, but related, issues arising: A typo in the wasmtime_val_unroot function in the C API meant that it did not actually unroot anything. This meant that even if embedders faithfully call the function then memory will be leaked. If a host-defined function returned a wasmtime_{externref,anyref}_t value then the value was never unrooted. The C/C++ API no longer has access to the value and the Rust implementation did not unroot. This meant that any values returned this way were never unrooted. The goal of the C++ API of Wasmtime is to encode automatic memory management in the type system, but the C++ API was not updated when OwnedRooted<T> was added. This meant that idiomatic usage of the C++ API would leak memory due to a lack of destructors on values.
These issues have all been fixed in a 37.0.2 release of Wasmtime. The implementation of the C and C++ APIs have been updated accordingly and respectively to account for the changes of ownership here. For example wasmtime_val_unroot has been fixed to unroot, the Rust-side implementation of calling an embedder-defined function will unroot return values, and the C++ API now has destructors on the ExternRef, AnyRef, and Val types. These changes have been made to the 37.0.x release branch in a non-API-breaking fashion. Changes to the 38.0.0 release branch (and main in the Wasmtime repository) include minor API updates to better accommodate the API semantic changes. The only known workaround at this time is to avoid using externref and anyref in the C/C++ API of Wasmtime. If avoiding those types is not possible then it's required for users to update to mitigate the leak issue.
- Record
CVE-2025-61670- CVSS 4.0
- 1.0 Low
CVSS:4.0/AV:A/AC:L/AT:P/PR:L/UI:P/VC:N/VI:N/VA:L/SC:N/SI:N/SA:L - Weakness
- CWE-772
- Updated
- 2026-11-02
OSVGHSA-vvp9-h8p2-xwfc
1.0
Wasmtime: Memory leak in C API with `externref` and `anyref` types
Impact
Wasmtime 37.0.0 and 37.0.1 have memory leaks in the C/C++ API when using bindings for the anyref or externref WebAssembly values. This is caused by a regression introduced during the development of 37.0.0 and all prior versions of Wasmtime are unaffected. If anyref or externref is not used in the C/C++ API then embeddings are also unaffected by the leaky behavior. The wasmtime Rust crate is unaffected by this leak.
Development of Wasmtime 37.0.0 included a refactoring in Rust of changing the old ManuallyRooted<T> type to a new OwnedRooted<T> type. This change was integrated into Wasmtime's C API but left the C API in a state which had memory leaks. Additionally the new ownership semantics around this type were not reflected into the C++ API, making it leak-prone. A short version of the change is that previously ManuallyRooted<T>, as the name implies, required manual calls to an "unroot" operation. If this was forgotten then the memory was still cleaned up when the wasmtime_store_t itself was destroyed eventually. Documentation of when to "unroot" was sparse and there were already situations prior to 37.0.0 where memory would be leaked until the store was destroyed anyway. All memory, though, was always bound by the store, and destroying the store would guarantee that there were no memory leaks.
In migrating to OwnedRooted<T> the usage of the type in Rust changed. A manual "unroot" operation is no longer required and it happens naturally as a destructor of the OwnedRooted<T> type in Rust itself. These new resource ownership semantics were not fully integrated into the preexisting semantics of the C/C++ APIs in Wasmtime. A crucial distinction of OwnedRooted<T> vs ManuallyRooted<T> is that the OwnedRooted<T> type allocates host memory outside of the store. This means that if an OwnedRooted<T> is leaked then destroying a store does not release this memory and it's a permanent memory leak on the host. This led to a few distinct, but related, issues arising:
- A typo in the
wasmtime_val_unrootfunction in the C API meant that it did not actually unroot anything. This meant that even if embedders faithfully call the function then memory will be leaked. - If a host-defined function returned a
wasmtime_{externref,anyref}_tvalue then the value was never unrooted. The C/C++ API no longer has access to the value and the Rust implementation did not unroot. This meant that any values returned this way were never unrooted. - The goal of the C++ API of Wasmtime is to encode automatic memory management in the type system, but the C++ API was not updated when
OwnedRooted<T>was added. This meant that idiomatic usage of the C++ API would leak memory due to a lack of destructors on values.
These issues have all been fixed in a 37.0.2 release of Wasmtime. The implementation of the C and C++ APIs have been updated accordingly and respectively to account for the changes of ownership here. For example wasmtime_val_unroot has been fixed to unroot, the Rust-side implementation of calling an embedder-defined function will unroot return values, and the C++ API now has destructors on the ExternRef, AnyRef, and Val types. These changes have been made to the 37.0.x release branch in a non-API-breaking fashion. Changes to the 38.0.0 release branch (and main in the Wasmtime repository) include minor API updates to better accomodate the API semantic changes.
Patches
Wasmtime 37.0.2 has been released which fixes these issues. Users of 37.0.0 and 37.0.1 are recommended to upgrade. Users of 36.0.x and prior are unaffected and need not upgrade.
Workarounds
The only known workaround at this time is to avoid using externref and anyref in the C/C++ API of Wasmtime. If avoiding those types is not possible then it's required for users to update to mitigate the leak issue.
Remediations
The Wasmtime project will be looking more closely into improving the situation around testing the C…
- Record
GHSA-vvp9-h8p2-xwfc- CVSS 4.0
- 1.0 Low
CVSS:4.0/AV:A/AC:L/AT:P/PR:L/UI:P/VC:N/VI:N/VA:L/SC:N/SI:N/SA:L - CVSS 3.1
- 3.3 Low
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:L - Weakness
- CWE-772
- Updated
- 2026-11-02
OSVPYSEC-2025-268
3.3
Wasmtime is a runtime for WebAssembly. Wasmtime 37.0.0 and 37.0.1 have memory leaks in the C/C++ API when using bindings for the anyref or externref WebAssembly values. This is caused by a regression introduced during the development of 37.0.0 and all prior versions of Wasmtime are unaffected. If anyref or externref is not used in the C/C++ API then embeddings are also unaffected by the leaky behavior. The wasmtime Rust crate is unaffected by this leak.
Development of Wasmtime 37.0.0 included a refactoring in Rust of changing the old ManuallyRooted<T> type to a new OwnedRooted<T> type. This change was integrated into Wasmtime's C API but left the C API in a state which had memory leaks. Additionally the new ownership semantics around this type were not reflected into the C++ API, making it leak-prone. A short version of the change is that previously ManuallyRooted<T>, as the name implies, required manual calls to an "unroot" operation. If this was forgotten then the memory was still cleaned up when the wasmtime_store_t itself was destroyed eventually. Documentation of when to "unroot" was sparse and there were already situations prior to 37.0.0 where memory would be leaked until the store was destroyed anyway. All memory, though, was always bound by the store, and destroying the store would guarantee that there were no memory leaks.
In migrating to OwnedRooted<T> the usage of the type in Rust changed. A manual "unroot" operation is no longer required and it happens naturally as a destructor of the OwnedRooted<T> type in Rust itself. These new resource ownership semantics were not fully integrated into the preexisting semantics of the C/C++ APIs in Wasmtime. A crucial distinction of OwnedRooted<T> vs ManuallyRooted<T> is that the OwnedRooted<T> type allocates host memory outside of the store. This means that if an OwnedRooted<T> is leaked then destroying a store does not release this memory and it's a permanent memory leak on the host.
This led to a few distinct, but related, issues arising: A typo in the wasmtime_val_unroot function in the C API meant that it did not actually unroot anything. This meant that even if embedders faithfully call the function then memory will be leaked. If a host-defined function returned a wasmtime_{externref,anyref}_t value then the value was never unrooted. The C/C++ API no longer has access to the value and the Rust implementation did not unroot. This meant that any values returned this way were never unrooted. The goal of the C++ API of Wasmtime is to encode automatic memory management in the type system, but the C++ API was not updated when OwnedRooted<T> was added. This meant that idiomatic usage of the C++ API would leak memory due to a lack of destructors on values.
These issues have all been fixed in a 37.0.2 release of Wasmtime. The implementation of the C and C++ APIs have been updated accordingly and respectively to account for the changes of ownership here. For example wasmtime_val_unroot has been fixed to unroot, the Rust-side implementation of calling an embedder-defined function will unroot return values, and the C++ API now has destructors on the ExternRef, AnyRef, and Val types. These changes have been made to the 37.0.x release branch in a non-API-breaking fashion. Changes to the 38.0.0 release branch (and main in the Wasmtime repository) include minor API updates to better accommodate the API semantic changes. The only known workaround at this time is to avoid using externref and anyref in the C/C++ API of Wasmtime. If avoiding those types is not possible then it's required for users to update to mitigate the leak issue.
- Record
PYSEC-2025-268- CVSS 3.1
- 3.3 Low
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:L - Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
wasmtime-c-api-implcrates.io |
37.0.0 up to 37.0.2 | 37.0.2 |
wasmtime-binPyPI |
before 37.0.2 | 37.0.2 |
wasmtime-binPyPI |
before 37.0.2, plus listed versions 36.0.9 |
37.0.2 |
wasmtime-binPyPI |
through 37.0.0, through 37.0.1, plus listed versions 36.0.9 |
None known |
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2025-61670 is a low vulnerability (CVSS 1.0) in Bytecodealliance Wasmtime, published October 7, 2025. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.19%, the 9th percentile. Fixed in wasmtime-c-api-impl 37.0.2.
References
github.com/bytecodealliance/wasmtime/security/advisories/GHSA-vvp9-h8p2-xwfc
github.com/bytecodealliance/wasmtime/commit/adff9d9d0f09569203709d5687e5a7dc8e1ad0a3
github.com/bytecodealliance/wasmtime/releases/tag/v37.0.2
nvd.nist.gov/vuln/detail/CVE-2025-61670
github.com/pypa/advisory-database/tree/main/vulns/wasmtime-bin/PYSEC-2025-268.yaml
github.com/advisories/GHSA-vvp9-h8p2-xwfc
github.com/CVEProject/cvelistV5/tree/main/cves/2025/61xxx/CVE-2025-61670.json
github.com/bytecodealliance/wasmtime
Left out here: the rest of 2 source descriptions. The JSON record has them.