CVE-2026-23519: Silent Cryptographic Timing Leak in RustCrypto cmov on ARM Cortex-M

Vulnerability Overview (At a Glance)

FieldDetails
CVE IDCVE-2026-23519
Affected ComponentRustCrypto cmov crate (portable cmovnz implementation)
Affected Versionscmov < 0.4.4
Fixed Versioncmov 0.4.4
CVSS Score8.9 (High)
SeverityHigh
Vulnerability TypeCryptographic Side-Channel (Timing)
ExploitabilityDifficult but feasible in controlled environments
Exploit AvailabilityProof-of-concept available (educational/research use only)
Attack VectorTiming observation during cryptographic operations
ImpactPotential leakage of secret-dependent values
Primary RiskLoss of confidentiality
Platforms ImpactedARM Cortex-M (thumbv6m-none-eabi: M0/M0+/M1)

What This Vulnerability Really Is

This vulnerability is not a memory corruption bug, not a crash, and not remotely exploitable in the traditional sense.
It is a cryptographic side-channel flaw.

The RustCrypto cmov crate is designed to provide constant-time conditional move operations. These operations are critical in cryptography because they avoid branches that depend on secret values.

However, on very small ARM embedded CPUs (specifically thumbv6m-none-eabi targets), the portable fallback implementation of cmovnz is compiled by the Rust compiler/LLVM in a way that introduces conditional branching.

Once branching appears, execution time becomes dependent on secret data.

That breaks the core promise of constant-time execution.


Why This Happened

  1. The cmov crate has:
    • Assembly-based constant-time implementations for many architectures
    • A portable Rust fallback for platforms without inline assembly support
  2. On thumbv6m-none-eabi, the portable fallback is used.
  3. The fallback uses bit-manipulation logic that should remain branchless.
  4. LLVM optimizes part of that logic into:
    • Boolean evaluation
    • Followed by a conditional branch (bne, beq)
  5. That branch depends on data derived from secret input.
  6. Result: timing differences that correlate with secret values

This is not a coding mistake in Rust itself, but a compiler optimization side effect that invalidated constant-time assumptions.


Security Impact

If cryptographic code relies on this cmovnz operation:

  • Signature verification
  • Key comparison
  • MAC verification
  • Password / secret checks

An attacker who can:

  • Repeatedly trigger the operation
  • Measure execution time with sufficient precision

may be able to infer bits of secret data over many measurements.

This is especially relevant for:

  • Embedded devices
  • IoT firmware
  • Hardware wallets
  • Secure microcontrollers
  • Smart cards or secure boot chains

Exploitation Details (Educational)

Is exploitation easy?

No. This is not a script-kiddie bug.

What an attacker needs:

  • Ability to invoke the vulnerable operation repeatedly
  • High-resolution timing measurements
  • Stable execution environment
  • Many samples (thousands to millions)

What can be leaked:

  • Bits or patterns derived from secret values
  • Not full secrets instantly, but incremental leakage

Why it still matters:

  • Side-channel attacks are cumulative
  • Embedded devices often run for years
  • Attackers with physical or co-located access can exploit this

Proof-of-Concept (PoC)

A minimal proof-of-concept exists that demonstrates:

  • The compiled assembly for thumbv6m-none-eabi
  • Presence of conditional branch instructions inside cmovnz
  • Observable execution differences

The PoC is educational and verification-focused, not weaponized.

It proves:

  • The operation is not constant time
  • The vulnerability is real and measurable

How to Detect If You Are Affected

1. Dependency Inspection

Check whether your project (or its dependencies) uses:

  • cmov crate
  • Version lower than 0.4.4

This applies to:

  • Direct dependencies
  • Transitive dependencies

2. Target Inspection

You are at risk only if all of the following are true:

  • Target architecture is thumbv6m-none-eabi
  • Portable cmov fallback is used
  • Code handles secret data
  • Timing can be measured

3. Assembly Inspection

Build your project and inspect generated assembly:

  • Look for bne, beq, or similar branches
  • Inside functions originating from cmov portable code

If branching is present → not constant time


4. Runtime Timing Test

Create a test loop that:

  • Calls cmovnz repeatedly
  • Varies secret inputs
  • Measures cycle counts

If timing correlates with input → vulnerable build


Detection Data Sources

SourceValue
CI build logsDependency version checks
Cargo.lockDefinitive version resolution
SBOM (CycloneDX/SPDX)Long-term inventory
Firmware binariesAssembly inspection
Lab timing logsSide-channel validation

MITRE Mapping

  • CWE-208 – Observable Timing Discrepancy
  • CWE-385 – Covert Timing Channel

This vulnerability directly maps to confidentiality loss via side-channel observation.


What This Vulnerability Does Not Do

  • Does not crash systems
  • Does not allow code execution
  • Does not bypass authentication directly
  • Does not show obvious logs or alerts

This is a silent weakness, not an active exploit signal.


Official Fix

Upgrade to cmov version 0.4.4 or later

Official advisory and patch (includes fix details and commit):

👉 https://github.com/RustCrypto/utils/security/advisories/GHSA-2gqc-6j2q-83qp


Recommended Mitigation Steps

  1. Upgrade cmov to ≥ 0.4.4
  2. Rebuild all affected firmware or binaries
  3. Redeploy embedded images
  4. Add CI enforcement
  5. Track dependencies via SBOM
  6. Avoid assuming “portable” means “constant-time”

CI Protection: GitHub Actions Bash Script

Below is a drop-in bash script that fails builds if a vulnerable cmov version is detected.

CI Script (Bash)

#!/usr/bin/env bash
set -euo pipefail

echo "[*] Checking for vulnerable cmov versions..."

if ! command -v cargo >/dev/null 2>&1; then
  echo "[!] Cargo not found. Skipping cmov check."
  exit 0
fi

VULN_FOUND=0

cargo tree -e normal | while read -r line; do
  if echo "$line" | grep -E "cmov v0\.[0-3]\." >/dev/null; then
    echo "[!] Vulnerable cmov detected: $line"
    VULN_FOUND=1
  fi
done

if [ "$VULN_FOUND" -eq 1 ]; then
  echo "[X] Build blocked: cmov version < 0.4.4 is present."
  exit 1
else
  echo "[✓] No vulnerable cmov versions detected."
fi

How to Use

  • Place this script in your repository (e.g., ci/check_cmov.sh)
  • Call it from GitHub Actions before build or release
  • Ensures vulnerable firmware is never shipped

Final Takeaway

This vulnerability is subtle but serious.

It does not break systems loudly, but it weakens cryptographic guarantees silently, which is often worse in embedded and security-critical environments.

If you build cryptographic software for Cortex-M devices and rely on RustCrypto utilities:

Upgrading is mandatory, not optional.


Aegiron

Backed by 11+ years in cybersecurity and incident response, we decode the latest threats shaping today’s digital battlefield. This blog cuts through the noise with clear insights on vulnerabilities, emerging exploits, and the cyber news defenders can’t afford to miss.