Skip to content

GHSA-7qmx-3fpx-r45m CVE-2024-47813 PYSEC-2024-311 RUSTSEC-2024-0439

Wasmtime race condition could lead to WebAssembly control-flow integrity and type safety violations

Low PyPIcrates.io
Severity
0.0 / 10
Low · CVSS 4.0
Exploit chance (EPSS)
0.15%
Chance of exploitation in the next 30 days. Higher than 4.41% of scored vulnerabilities.
Known exploited
No
Not in CISA's catalog
Weakness
CWE-367 Time-of-check Time-of-use (TOCTOU) Race Condition
Fix
21.0.2
Upgrade wasmtime to this version or later

Description

Impact

Under certain concurrent event orderings, a wasmtime::Engine's internal type registry was susceptible to double-unregistration bugs due to a race condition, leading to panics and potentially type registry corruption. That registry corruption could, following an additional and particular sequence of concurrent events, lead to violations of WebAssembly's control-flow integrity (CFI) and type safety. Users that do not use wasmtime::Engine across multiple threads are not affected. Users that only create new modules across threads over time are additionally not affected.

Reproducing this bug requires creating and dropping multiple type instances (such as wasmtime::FuncType or wasmtime::ArrayType) concurrently on multiple threads, where all types are associated with the same wasmtime::Engine. Wasm guests cannot trigger this bug. See the "References" section below for a list of Wasmtime types-related APIs that are affected.

Wasmtime maintains an internal registry of types within a wasmtime::Engine and an engine is shareable across threads. Types can be created and referenced through creation of a wasmtime::Module, creation of wasmtime::FuncType, or a number of other APIs where the host creates a function (see "References" below). Each of these cases interacts with an engine to deduplicate type information and manage type indices that are used to implement type checks in WebAssembly's call_indirect function, for example. This bug is a race condition in this management where the internal type registry could be corrupted to trigger an assert or contain invalid state.

Wasmtime's internal representation of a type has individual types (e.g. one-per-host-function) maintain a registration count of how many time it's been used. Types additionally have state within an engine behind a read-write lock such as lookup/deduplication information. The race here is a time-of-check versus time-of-use (TOCTOU) bug where one thread atomically decrements a type entry's registration count, observes zero registrations, and then acquires a lock in order to unregister that entry. However, between when this first thread observed the zero-registration count and when it acquires that lock, another thread could perform the following sequence of events: re-register another copy of the type, which deduplicates to that same entry, resurrecting it and incrementing its registration count; then drop the type and decrement its registration count; observe that the registration count is now zero; acquire the type registry lock; and finally unregister the type. Now, when the original thread finally acquires the lock and unregisters the entry, it is the second time this entry has been unregistered.

Thread A Thread B
acquire(type registry lock)
decref(E) --> 0
block_on(type registry lock)
register(E') == incref(E) --> 1
release(type registry lock)
decref(E) --> 0
acquire(type registry lock)
unregister(E)
release(type registry lock)
acquire(type registry lock)
unregister(E)

This double-unregistration could then lead to a WebAssembly CFI violation under the following conditions: a new WebAssembly module X was loaded into the engine before the second, buggy unregistration occurs; X defined a function type F that was allocated in the same type registry slot where the original entry was allocated; the second, buggy unregistration incorrectly unregistered F; another new WebAssembly module Y was loaded into the engine; Y defined a function type G, different from F, but which is also allocated in the same type registry slot; a funcref of type G is created, either by the host or by Wasm; that funcref is passed to a WebAssembly instance of module X; that instance performs a call_indirect to that funcref; the call_indirect's dynamic type check, which preserves CFI, could incorrectly pass in this case, because F and G were assigned the same type registry slot. This would, ultimately, allow calling a function with too many, too few, or wrongly-typed arguments, violating CFI and type safety.

We were not able to reproduce this CFI violation in a vanilla Wasmtime build, although it remains theoretically possible. However, by modifying Wasmtime's source code to make losing the races described above more likely (by disabling certain assertions, inserting panic catches, and adding retry loops in a few places if we did not lose the race) we were able to incorrectly get a funcref to pass a type check that it should have failed, which would allow the CFI violation.

Patches

This bug was originally introduced in Wasmtime 19's development of the WebAssembly GC proposal. This bug affects users who are not using the GC proposal, however, and affects Wasmtime in its default configuration even when the GC proposal is disabled. Wasmtime users using 19.0.0 and after are all affected by this issue. We have released the following Wasmtime versions, all of which have a fix for this bug:

  • 21.0.2
  • 22.0.1
  • 23.0.3
  • 24.0.1
  • 25.0.2

Workarounds

If your application creates and drops Wasmtime types on multiple threads concurrently, there are no known workarounds. Users are encouraged to upgrade to a patched release.

References

The following APIs create or drop types, and therefore are affected by this race condition if performed on multiple threads concurrently and are all associated with the same wasmtime::Engine:

The change which introduced this bug was #7969

Affected versions

PyPI

PackageVulnerableFixed in
wasmtime
<= 19.0.0
<= 19.0.1
<= 19.0.2
<= 20.0.0
<= 20.0.1
<= 20.0.2
<= 21.0.0
<= 21.0.1
<= 22.0.0
<= 23.0.0
<= 23.0.1
<= 23.0.2
<= 24.0.0
<= 25.0.0
<= 25.0.1
No fix yet

crates.io

PackageVulnerableFixed in
wasmtime
>= 19.0.0, < 21.0.2
21.0.2
wasmtime
>= 22.0.0, < 22.0.1
22.0.1
wasmtime
>= 23.0.0, < 23.0.3
23.0.3
wasmtime
>= 24.0.0, < 24.0.1
24.0.1
wasmtime
>= 25.0.0, < 25.0.2
25.0.2
wasmtime
>= 19.0.0, < 21.0.2
>= 22.0.0, < 22.0.1
>= 23.0.0, < 23.0.3
>= 24.0.0, < 24.0.1
>= 25.0.0, < 25.0.2
21.0.2
22.0.1
23.0.3
24.0.1
25.0.2

How to fix

Move to the fixed version or later with your package manager, update the lockfile, and run your tests. If the package only arrives through another dependency, upgrade that dependency first. If none of its releases pulls a fixed version yet, force the version with your package manager's override.

wasmtime crates.io → 21.0.2

cargo
cargo update -p wasmtime --precise 21.0.2

Severity breakdown

CVSS 4.0 0.0

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

Attack vector
Local
Attack complexity
Low
Attack requirements
Present
Privileges required
High
User interaction
Active
Confidentiality (vulnerable system)
None
Integrity (vulnerable system)
Low
Availability (vulnerable system)
Low
Confidentiality (subsequent systems)
None
Integrity (subsequent systems)
None
Availability (subsequent systems)
None

CVSS 3.1 2.9

CVSS:3.1/AV:L/AC:H/PR:H/UI:R/S:U/C:N/I:L/A:L

Attack vector
Local
Attack complexity
High
Privileges required
High
User interaction
Required
Scope
Unchanged
Confidentiality
None
Integrity
Low
Availability
Low

Weakness

CWE-367: Time-of-check Time-of-use (TOCTOU) Race Condition

The product checks the state of a resource before using that resource, but the resource's state can change between the check and the use in a way that invalidates the results of the check.

How to prevent it
  • Implementation: The most basic advice for TOCTOU vulnerabilities is to not perform a check before the use. This does not resolve the underlying issue of the execution of a function on a resource whose state and identity cannot be assured, but it does help to limit the false sense of security given by the check.
  • Implementation: When the file being altered is owned by the current user and group, set the effective gid and uid to that of the current user and group when executing this statement.
  • Architecture and Design: Limit the interleaving of operations on files from multiple processes.
  • Implementation, Architecture and Design: If you cannot perform operations atomically and you must share access to the resource between multiple processes or threads, then try to limit the amount of time (CPU cycles) between the check and use of the resource. This will not fix the problem, but it could make it more difficult for an attack to succeed.
  • Implementation: Recheck the resource after the use call to verify that the action was taken appropriately.
  • Architecture and Design: Ensure that some environmental locking mechanism can be used to protect resources effectively.
  • Implementation: Ensure that locking occurs before the check, as opposed to afterwards, such that the resource, as checked, is the same as it is when in use.

References

Timeline

  1. Published
  2. Last updated by the source
  3. Latest EPSS score
AdvisorySeverityWhy it's related
RUSTSEC-2026-0424
Unchecked memory usage in transferring borrowed resources between components
Not rated yet Also affects wasmtime
RUSTSEC-2026-0423
Cross-engine type confusion with host-created struct-types-with-supertypes
Not rated yet Also affects wasmtime
RUSTSEC-2026-0422
Typed functions with `i31` or `nullref` arguments may panic due to insufficient type-check
Low Also affects wasmtime
RUSTSEC-2026-0379
Wasmtime: Cranelift backend on aarch64 can jump to incorrect target on large Wasm `br_table` instruction
Critical Also affects wasmtime
GHSA-9pvw-hwfg-92h5
Wasmtime: Panic lowering a host-created component model stream into a guest that expects a different payload type
Medium Also affects wasmtime
GHSA-897f-g5gm-fmxm
Wasmtime: Bit-packing in Cranelift compiler causes silent overflow and miscompilation
Critical Also affects wasmtime
RUSTSEC-2026-0364
Exception tags can cause host data structures to be unaligned
Not rated yet Also affects wasmtime
RUSTSEC-2026-0363
Component-model handle tables are capped only per instance and charged to no limit
Medium Also affects wasmtime
Is this in your code?

MergeHarbor checks every repository's dependencies against this database, ranks what matters by exploitability and reachability, routes it to the owning team and opens the fix pull request.

Check your repos with MergeHarbor