CVE-2020-35908
Description
An issue was discovered in the futures-util crate before 0.3.2 for Rust. FuturesUnordered can lead to data corruption because Sync is mishandled.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
CVE-2020-35908: Improper Sync implementation in futures-util's FuturesUnordered can cause data corruption in concurrent Rust programs.
Vulnerability
Overview
CVE-2020-35908 is a thread-safety vulnerability in the futures-util crate (part of the futures-rs library) for Rust, affecting versions prior to 0.3.2. The root cause is an improper implementation of the Sync trait on the FuturesUnordered type [1]. Specifically, after a refactoring that replaced RefCell with Cell for interior mutability of the len and head_all fields (in commit 47f3ccb), the existing Sync implementation was retained, although Cell provides no synchronization guarantees [4]. This violates Rust's thread-safety guarantees because Sync signals that a type is safe to share via shared references across threads, whereas FuturesUnordered does not perform any actual synchronization when mutating those fields (e.g., in the push method) [1][4].
Exploitation
Conditions
To exploit this vulnerability, an attacker must be able to construct a program that shares a FuturesUnordered instance across multiple threads using shared references. This typically requires local access to execute malicious code (CVSS attack vector: Local) and low privileges [1]. No user interaction is needed. The issue surfaces when concurrent, unsynchronized modifications to the FuturesUnordered's internal state are made, leading to data races [1][2].
Impact
An attacker exploiting this race condition can cause data corruption in internal data structures, ultimately leading to memory corruption [1]. Although confidentiality and integrity are not directly compromised, the impact on availability is rated High, as successful exploitation may result in crashes or unpredictable behavior [1]. The advisory classifies this as a memory-corruption and thread-safety vulnerability [1].
Mitigation
The vulnerability is fixed in futures-util version 0.3.2 [1][2]. Users should upgrade to at least that version. The fix involved removing the incorrect Sync implementation from FuturesUnordered, preventing its use across threads without explicit synchronization [1][4]. No workaround is available other than upgrading.
AI Insight generated on May 21, 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.
| Package | Affected versions | Patched versions |
|---|---|---|
futures-utilcrates.io | >= 0.3.0, < 0.3.2 | 0.3.2 |
Affected products
2- Rust/futures-utildescription
Patches
112 files changed · +60 −45
CHANGELOG.md+16 −1 modified@@ -1,5 +1,20 @@ -# 0.3.2 - 2020-??-?? +# 0.3.2 - 2020-02-03 +* Improved buffering performance of `SplitSink` (#1969) +* Added `select_biased!` macro (#1976) +* Added `hash_receiver` method to mpsc channel (#1962) +* Added `stream::try_unfold` (#1977) +* Fixed bug with zero-size buffers in vectored IO (#1998) +* `AtomicWaker::new()` is now `const fn` (#2007) +* Fixed bug between threadpool and user park/unparking (#2010) +* Added `stream::Peakable::peek` (#2021) +* Added `StreamExt::scan` (#2044) +* Added impl of `AsyncRead`/`Write` for `BufReader`/`Writer` (#2033) +* Added impl of `Spawn` and `LocalSpawn` for `Arc<impl Spawn` and `Rc<impl Spawn>` (#2039) +* Fixed `Sync` issues with `FuturesUnordered` (#2054) * Added `into_inner` method for `future::Ready` (#2055) +* Added `MappedMutexGuard` API (#2056) +* Mitigated starvation issues in `FuturesUnordered` (#2049) +* Added `TryFutureExt::map_ok_or_else` (#2058) # 0.3.1 - 2019-11-7 * Fix signature of `LocalSpawn` trait (breaking change -- see #1959)
futures/Cargo.toml+10 −10 modified@@ -1,7 +1,7 @@ [package] name = "futures" edition = "2018" -version = "0.3.1" +version = "0.3.2" authors = ["Alex Crichton <alex@alexcrichton.com>"] license = "MIT OR Apache-2.0" readme = "../README.md" @@ -19,18 +19,18 @@ categories = ["asynchronous"] travis-ci = { repository = "rust-lang/futures-rs" } [dependencies] -futures-core = { path = "../futures-core", version = "0.3.1", default-features = false } -futures-task = { path = "../futures-task", version = "0.3.1", default-features = false } -futures-channel = { path = "../futures-channel", version = "0.3.1", default-features = false, features = ["sink"] } -futures-executor = { path = "../futures-executor", version = "0.3.1", default-features = false, optional = true } -futures-io = { path = "../futures-io", version = "0.3.1", default-features = false } -futures-sink = { path = "../futures-sink", version = "0.3.1", default-features = false } -futures-util = { path = "../futures-util", version = "0.3.1", default-features = false, features = ["sink"] } +futures-core = { path = "../futures-core", version = "0.3.2", default-features = false } +futures-task = { path = "../futures-task", version = "0.3.2", default-features = false } +futures-channel = { path = "../futures-channel", version = "0.3.2", default-features = false, features = ["sink"] } +futures-executor = { path = "../futures-executor", version = "0.3.2", default-features = false, optional = true } +futures-io = { path = "../futures-io", version = "0.3.2", default-features = false } +futures-sink = { path = "../futures-sink", version = "0.3.2", default-features = false } +futures-util = { path = "../futures-util", version = "0.3.2", default-features = false, features = ["sink"] } [dev-dependencies] pin-utils = "0.1.0-alpha.4" -futures-executor = { path = "../futures-executor", version = "0.3.1", features = ["thread-pool"] } -futures-test = { path = "../futures-test", version = "0.3.1" } +futures-executor = { path = "../futures-executor", version = "0.3.2", features = ["thread-pool"] } +futures-test = { path = "../futures-test", version = "0.3.2" } tokio = "0.1.11" assert_matches = "1.3.0"
futures-channel/Cargo.toml+5 −5 modified@@ -1,7 +1,7 @@ [package] name = "futures-channel" edition = "2018" -version = "0.3.1" +version = "0.3.2" authors = ["Alex Crichton <alex@alexcrichton.com>"] license = "MIT OR Apache-2.0" repository = "https://github.com/rust-lang/futures-rs" @@ -24,12 +24,12 @@ unstable = ["futures-core/unstable"] cfg-target-has-atomic = ["futures-core/cfg-target-has-atomic"] [dependencies] -futures-core = { path = "../futures-core", version = "0.3.1", default-features = false } -futures-sink = { path = "../futures-sink", version = "0.3.1", default-features = false, optional = true } +futures-core = { path = "../futures-core", version = "0.3.2", default-features = false } +futures-sink = { path = "../futures-sink", version = "0.3.2", default-features = false, optional = true } [dev-dependencies] -futures = { path = "../futures", version = "0.3.1", default-features = true } -futures-test = { path = "../futures-test", version = "0.3.1", default-features = true } +futures = { path = "../futures", version = "0.3.2", default-features = true } +futures-test = { path = "../futures-test", version = "0.3.2", default-features = true } [package.metadata.docs.rs] all-features = true
futures-core/Cargo.toml+2 −2 modified@@ -1,7 +1,7 @@ [package] name = "futures-core" edition = "2018" -version = "0.3.1" +version = "0.3.2" authors = ["Alex Crichton <alex@alexcrichton.com>"] license = "MIT OR Apache-2.0" repository = "https://github.com/rust-lang/futures-rs" @@ -25,7 +25,7 @@ cfg-target-has-atomic = [] [dependencies] [dev-dependencies] -futures = { path = "../futures", version = "0.3.1" } +futures = { path = "../futures", version = "0.3.2" } [package.metadata.docs.rs] all-features = true
futures-executor/Cargo.toml+5 −5 modified@@ -1,7 +1,7 @@ [package] name = "futures-executor" edition = "2018" -version = "0.3.1" +version = "0.3.2" authors = ["Alex Crichton <alex@alexcrichton.com>"] license = "MIT OR Apache-2.0" repository = "https://github.com/rust-lang/futures-rs" @@ -17,13 +17,13 @@ std = ["futures-core/std", "futures-task/std", "futures-util/std"] thread-pool = ["std", "num_cpus"] [dependencies] -futures-core = { path = "../futures-core", version = "0.3.1", default-features = false } -futures-task = { path = "../futures-task", version = "0.3.1", default-features = false } -futures-util = { path = "../futures-util", version = "0.3.1", default-features = false } +futures-core = { path = "../futures-core", version = "0.3.2", default-features = false } +futures-task = { path = "../futures-task", version = "0.3.2", default-features = false } +futures-util = { path = "../futures-util", version = "0.3.2", default-features = false } num_cpus = { version = "1.8.0", optional = true } [dev-dependencies] -futures = { path = "../futures", version = "0.3.1" } +futures = { path = "../futures", version = "0.3.2" } [package.metadata.docs.rs] all-features = true
futures-io/Cargo.toml+1 −1 modified@@ -1,7 +1,7 @@ [package] name = "futures-io" edition = "2018" -version = "0.3.1" +version = "0.3.2" authors = ["Alex Crichton <alex@alexcrichton.com>"] license = "MIT OR Apache-2.0" repository = "https://github.com/rust-lang/futures-rs"
futures-macro/Cargo.toml+1 −1 modified@@ -1,7 +1,7 @@ [package] name = "futures-macro" edition = "2018" -version = "0.3.1" +version = "0.3.2" authors = ["Taylor Cramer <cramertj@google.com>", "Taiki Endo <te316e89@gmail.com>"] license = "MIT OR Apache-2.0" repository = "https://github.com/rust-lang/futures-rs"
futures-sink/Cargo.toml+1 −1 modified@@ -1,7 +1,7 @@ [package] name = "futures-sink" edition = "2018" -version = "0.3.1" +version = "0.3.2" authors = ["Alex Crichton <alex@alexcrichton.com>"] license = "MIT OR Apache-2.0" repository = "https://github.com/rust-lang/futures-rs"
futures-task/Cargo.toml+2 −2 modified@@ -1,7 +1,7 @@ [package] name = "futures-task" edition = "2018" -version = "0.3.1" +version = "0.3.2" authors = ["Alex Crichton <alex@alexcrichton.com>"] license = "MIT OR Apache-2.0" repository = "https://github.com/rust-lang/futures-rs" @@ -25,7 +25,7 @@ cfg-target-has-atomic = [] [dependencies] [dev-dependencies] -futures = { path = "../futures", version = "0.3.1" } +futures = { path = "../futures", version = "0.3.2" } [package.metadata.docs.rs] all-features = true
futures-test/Cargo.toml+7 −7 modified@@ -1,7 +1,7 @@ [package] name = "futures-test" edition = "2018" -version = "0.3.1" +version = "0.3.2" authors = ["Wim Looman <wim@nemo157.com>"] license = "MIT OR Apache-2.0" repository = "https://github.com/rust-lang/futures-rs" @@ -12,15 +12,15 @@ Common utilities for testing components built off futures-rs. """ [dependencies] -futures-core = { version = "0.3.1", path = "../futures-core", default-features = false } -futures-task = { version = "0.3.1", path = "../futures-task", default-features = false } -futures-io = { version = "0.3.1", path = "../futures-io", default-features = false } -futures-util = { version = "0.3.1", path = "../futures-util", default-features = false } -futures-executor = { version = "0.3.1", path = "../futures-executor", default-features = false } +futures-core = { version = "0.3.2", path = "../futures-core", default-features = false } +futures-task = { version = "0.3.2", path = "../futures-task", default-features = false } +futures-io = { version = "0.3.2", path = "../futures-io", default-features = false } +futures-util = { version = "0.3.2", path = "../futures-util", default-features = false } +futures-executor = { version = "0.3.2", path = "../futures-executor", default-features = false } pin-utils = { version = "0.1.0-alpha.4", default-features = false } [dev-dependencies] -futures = { version = "0.3.1", path = "../futures", default-features = false, features = ["std"] } +futures = { version = "0.3.2", path = "../futures", default-features = false, features = ["std"] } [features] default = ["std"]
futures-util/Cargo.toml+9 −9 modified@@ -1,7 +1,7 @@ [package] name = "futures-util" edition = "2018" -version = "0.3.1" +version = "0.3.2" authors = ["Alex Crichton <alex@alexcrichton.com>"] license = "MIT OR Apache-2.0" repository = "https://github.com/rust-lang/futures-rs" @@ -32,12 +32,12 @@ bilock = [] read-initializer = ["io", "futures-io/read-initializer", "futures-io/unstable"] [dependencies] -futures-core = { path = "../futures-core", version = "0.3.1", default-features = false } -futures-task = { path = "../futures-task", version = "0.3.1", default-features = false } -futures-channel = { path = "../futures-channel", version = "0.3.1", default-features = false, features = ["std"], optional = true } -futures-io = { path = "../futures-io", version = "0.3.1", default-features = false, features = ["std"], optional = true } -futures-sink = { path = "../futures-sink", version = "0.3.1", default-features = false, optional = true } -futures-macro = { path = "../futures-macro", version = "0.3.1", default-features = false, optional = true } +futures-core = { path = "../futures-core", version = "0.3.2", default-features = false } +futures-task = { path = "../futures-task", version = "0.3.2", default-features = false } +futures-channel = { path = "../futures-channel", version = "0.3.2", default-features = false, features = ["std"], optional = true } +futures-io = { path = "../futures-io", version = "0.3.2", default-features = false, features = ["std"], optional = true } +futures-sink = { path = "../futures-sink", version = "0.3.2", default-features = false, optional = true } +futures-macro = { path = "../futures-macro", version = "0.3.2", default-features = false, optional = true } proc-macro-hack = { version = "0.5.9", optional = true } proc-macro-nested = { version = "0.1.2", optional = true } slab = { version = "0.4", optional = true } @@ -47,8 +47,8 @@ tokio-io = { version = "0.1.9", optional = true } pin-utils = "0.1.0-alpha.4" [dev-dependencies] -futures = { path = "../futures", version = "0.3.1", features = ["async-await"] } -futures-test = { path = "../futures-test", version = "0.3.1" } +futures = { path = "../futures", version = "0.3.2", features = ["async-await"] } +futures-test = { path = "../futures-test", version = "0.3.2" } tokio = "0.1.11" [package.metadata.docs.rs]
README.md+1 −1 modified@@ -58,7 +58,7 @@ a `#[no_std]` environment, use: ```toml [dependencies] -futures = { version = "0.3.1", default-features = false } +futures = { version = "0.3.2", default-features = false } ``` # License
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
4- github.com/advisories/GHSA-5r9g-j7jj-hw6cghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2020-35908ghsaADVISORY
- github.com/rust-lang/futures-rs/issues/2050ghsaWEB
- rustsec.org/advisories/RUSTSEC-2020-0062.htmlghsax_refsource_MISCWEB
News mentions
0No linked articles in our index yet.