---
id: CVE-2026-23519
aliases:
  - RUSTSEC-2026-0003
  - GHSA-2gqc-6j2q-83qp
title: Non-constant-time code generation on ARM32 targets
summary: Non-constant-time code generation on ARM32 targets
severity: high
vendor: cmov
product: cmov
ecosystem: rust
affected:
  - 'cmov >= 0.0.0-0, < 0.4.4'
patched:
  - cmov 0.4.4
published: '2026-01-14'
updated: '2026-10-23'
sourceUpdated: '2026-10-23T08:41:35.268663457Z'
source: OSV
sourceUrl: 'https://osv.dev/vulnerability/RUSTSEC-2026-0003'
references:
  - url: 'https://crates.io/crates/cmov'
  - url: 'https://rustsec.org/advisories/RUSTSEC-2026-0003.html'
  - url: >-
      https://github.com/RustCrypto/utils/commit/55977257e7c82a309d5e8abfdd380a774f0f9778
  - url: >-
      https://github.com/RustCrypto/utils/security/advisories/GHSA-2gqc-6j2q-83qp
  - url: 'https://nvd.nist.gov/vuln/detail/CVE-2026-23519'
  - url: 'https://github.com/RustCrypto/utils'
tags:
  - osv
  - rust
epss: 0.00558
epssPercentile: 0.46291
ingestedAt: '2026-08-07T19:14:19.490Z'
---

## Overview

## 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:

```asm
    bne  .LBB0_2
    mvns r3, r3
```

This includes a branch instruction `bne`: Branch if Not Equal.

## PoC

The following code reproduces the issue:

```rust
#![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 packages

- `cmov >= 0.0.0-0, < 0.4.4`

## Remediation

Upgrade to a patched release:

- `cmov 0.4.4`
