rustsec-2026-0003
Vulnerability from osv_rustsec
Summary
While the cmov crate has a special backend for aarch64 which uses special
CSEL instructions, on 32-bit ARM it uses a portable pure Rust fallback
implementation. This implementation uses a combination of bitwise arithmetic
and core::hint::black_box to attempt to coerce constant-time code generation
out of the optimizer, but the implementation in v0.4.3 and earlier failed to
do this on 32-bit ARM targets.
Impact
Branch instructions inserted by the LLVM optimizer on 32-bit targets can be
leveraged using various microarchitectural sidechannels like cache timing
attacks to learn secret information that cmov is designed to protect.
Details
The following assembly was emitted when using Cmov::cmovnz, a function which
implements a conditional move when a provided value is non-zero:
bne .LBB0_2
mvns r3, r3
This includes a branch instruction bne: Branch if Not Equal.
PoC
The following code reproduces the issue:
#![no_std]
use cmov::Cmov;
#[inline(never)]
pub fn test_ct_cmov(a: &mut u8, b: u8, c: u8) {
a.cmovnz(&b, c);
}
Resolution
cmov v0.4.4 includes a portable black_box-based tactical mitigation for the
issue which coerced the compiler into producing the expected codegen, and
additionally v0.4.5 added an asm! reimplementation of the problematic mask
generation function for ARM32 targets which should guarantee that particular
function never contains a branch on such targets.
{
"affected": [
{
"database_specific": {
"categories": [
"crypto-failure"
],
"cvss": "CVSS:4.0/AV:N/AC:H/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:H/SI:N/SA:N",
"informational": null
},
"ecosystem_specific": {
"affected_functions": null,
"affects": {
"arch": [],
"functions": [],
"os": []
}
},
"package": {
"ecosystem": "crates.io",
"name": "cmov",
"purl": "pkg:cargo/cmov"
},
"ranges": [
{
"events": [
{
"introduced": "0.0.0-0"
},
{
"fixed": "0.4.4"
}
],
"type": "SEMVER"
}
],
"versions": []
}
],
"aliases": [
"CVE-2026-23519",
"GHSA-2gqc-6j2q-83qp"
],
"database_specific": {
"license": "CC-BY-4.0"
},
"details": "## Summary\n\nWhile the `cmov` crate has a special backend for `aarch64` which uses special\nCSEL instructions, on 32-bit ARM it uses a portable pure Rust fallback\nimplementation. This implementation uses a combination of bitwise arithmetic\nand `core::hint::black_box` to attempt to coerce constant-time code generation\nout of the optimizer, but the implementation in v0.4.3 and earlier failed to\ndo this on 32-bit ARM targets.\n\n## Impact\n\nBranch instructions inserted by the LLVM optimizer on 32-bit targets can be\nleveraged using various microarchitectural sidechannels like cache timing\nattacks to learn secret information that `cmov` is designed to protect.\n\n## Details\n\nThe following assembly was emitted when using `Cmov::cmovnz`, a function which\nimplements a conditional move when a provided value is non-zero:\n\n```asm\n bne .LBB0_2\n mvns r3, r3\n```\n\nThis includes a branch instruction `bne`: Branch if Not Equal.\n\n## PoC\n\nThe following code reproduces the issue:\n\n```rust\n#![no_std]\nuse cmov::Cmov;\n\n#[inline(never)]\npub fn test_ct_cmov(a: \u0026mut u8, b: u8, c: u8) {\n a.cmovnz(\u0026b, c);\n}\n```\n\n## Resolution\n\n`cmov` v0.4.4 includes a portable `black_box`-based tactical mitigation for the\nissue which coerced the compiler into producing the expected codegen, and\nadditionally v0.4.5 added an `asm!` reimplementation of the problematic mask\ngeneration function for ARM32 targets which should guarantee that particular\nfunction never contains a branch on such targets.",
"id": "RUSTSEC-2026-0003",
"modified": "2026-01-15T17:45:42Z",
"published": "2026-01-14T12:00:00Z",
"references": [
{
"type": "PACKAGE",
"url": "https://crates.io/crates/cmov"
},
{
"type": "ADVISORY",
"url": "https://rustsec.org/advisories/RUSTSEC-2026-0003.html"
},
{
"type": "ADVISORY",
"url": "https://github.com/RustCrypto/utils/security/advisories/GHSA-2gqc-6j2q-83qp"
}
],
"related": [],
"severity": [
{
"score": "CVSS:4.0/AV:N/AC:H/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:H/SI:N/SA:N",
"type": "CVSS_V4"
}
],
"summary": "Non-constant-time code generation on ARM32 targets"
}
Sightings
| Author | Source | Type | Date |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.