GHSA-2GQC-6J2Q-83QP

Vulnerability from github – Published: 2026-01-15 18:17 – Updated: 2026-01-23 21:46
VLAI
Summary
RustCrypto Utilities cmov: `thumbv6m-none-eabi` compiler emits non-constant time assembly when using `cmovnz`
Details

Summary

thumbv6m-none-eabi (Cortex M0, M0+ and M1) compiler emits non-constant time assembly when using cmovnz (portable version). I did not found any other target with the same behaviour but I did not go through all targets supported by Rust.

Details

It seems that, during mask computation, an LLVM optimisation pass is detecting that bitnz is returning 0 or 1, that can be interpreted as a boolean. This intermediate value is not masked by a call to black_box and thus the subsequent .wrapping_sub(1) can be interpreted as a conditional bitwise conditional not.

PoC

This is an attempt at having a minimal faulty code. In a library crate with an up-to-date cmov as only dependency, the content of src/lib.rs is:

#![no_std]
use cmov::Cmov;

#[inline(never)]
pub fn test_ct_cmov(a: &mut u8, b: u8, c: u8) {
    a.cmovnz(&b, c);
}

The resulting assembly emitted (shown using cargo asm --release --target thumbv6m-none-eabi that uses cargo-show-asm):

Collapsed assembly
.section .text.not_ct::test_ct_cmov,"ax",%progbits
    .globl  not_ct::test_ct_cmov
    .p2align    1
    .type   not_ct::test_ct_cmov,%function
    .code   16
    .thumb_func
not_ct::test_ct_cmov:
    .fnstart
    .cfi_sections .debug_frame
    .cfi_startproc
    .save   {r7, lr}
    push {r7, lr}
    .cfi_def_cfa_offset 8
    .cfi_offset lr, -4
    .cfi_offset r7, -8
    .setfp  r7, sp
    add r7, sp, #0
    .cfi_def_cfa_register r7
    .pad    #8
    sub sp, #8
    movs r3, #0
    lsls r2, r2, #24
    bne .LBB0_2
    mvns r3, r3
.LBB0_2:
    ldrb r2, [r0]
    str r3, [sp, #4]
    str r3, [sp]
    mov r3, sp
    @APP
    @NO_APP
    ldr r3, [sp]
    bics r1, r3
    ands r2, r3
    adds r1, r2, r1
    strb r1, [r0]
    add sp, #8
    pop {r7, pc}

The non-constant time assembly is:

    bne  .LBB0_2
    mvns r3, r3
.LBB0_2:

Impact

The exact impact is unclear, especially since cmov clearly warns users that the portable version is best-effort.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "crates.io",
        "name": "cmov"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "0.4.4"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-23519"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-203",
      "CWE-208"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-01-15T18:17:15Z",
    "nvd_published_at": "2026-01-15T20:16:05Z",
    "severity": "HIGH"
  },
  "details": "### Summary\n\n`thumbv6m-none-eabi` (Cortex M0, M0+ and M1) compiler emits non-constant time assembly when using `cmovnz` (portable version). I did not found any other target with the same behaviour but I did not go through all targets supported by Rust. \n\n### Details\n\nIt seems that, [during `mask` computation](https://github.com/RustCrypto/utils/blob/9e555db060c80f4669d804f448a524a37d201b32/cmov/src/portable.rs#L78), an LLVM optimisation pass is detecting that [`bitnz`](https://github.com/RustCrypto/utils/blob/9e555db060c80f4669d804f448a524a37d201b32/cmov/src/portable.rs#L13) is returning 0 or 1, that can be interpreted as a boolean. This intermediate value is not masked by a call to `black_box` and thus the subsequent [`.wrapping_sub(1)`](https://github.com/RustCrypto/utils/blob/9e555db060c80f4669d804f448a524a37d201b32/cmov/src/portable.rs#L78C1-L78C84) can be interpreted as a conditional bitwise conditional not.\n\n### PoC\n\nThis is an attempt at having a minimal faulty code. In a library crate with an up-to-date `cmov` as only dependency, the content of `src/lib.rs` is:\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\nThe resulting assembly emitted (shown using `cargo asm --release --target thumbv6m-none-eabi` that uses [`cargo-show-asm`](https://crates.io/crates/cargo-show-asm)):\n\n\u003cdetails\u003e\n\u003csummary\u003eCollapsed assembly\u003c/summary\u003e\n\n```asm\n.section .text.not_ct::test_ct_cmov,\"ax\",%progbits\n\t.globl\tnot_ct::test_ct_cmov\n\t.p2align\t1\n\t.type\tnot_ct::test_ct_cmov,%function\n\t.code\t16\n\t.thumb_func\nnot_ct::test_ct_cmov:\n\t.fnstart\n\t.cfi_sections .debug_frame\n\t.cfi_startproc\n\t.save\t{r7, lr}\n\tpush {r7, lr}\n\t.cfi_def_cfa_offset 8\n\t.cfi_offset lr, -4\n\t.cfi_offset r7, -8\n\t.setfp\tr7, sp\n\tadd r7, sp, #0\n\t.cfi_def_cfa_register r7\n\t.pad\t#8\n\tsub sp, #8\n\tmovs r3, #0\n\tlsls r2, r2, #24\n\tbne .LBB0_2\n\tmvns r3, r3\n.LBB0_2:\n\tldrb r2, [r0]\n\tstr r3, [sp, #4]\n\tstr r3, [sp]\n\tmov r3, sp\n\t@APP\n\t@NO_APP\n\tldr r3, [sp]\n\tbics r1, r3\n\tands r2, r3\n\tadds r1, r2, r1\n\tstrb r1, [r0]\n\tadd sp, #8\n\tpop {r7, pc}\n```\n\n\u003c/details\u003e\n\nThe non-constant time assembly is:\n\n```asm\n    bne  .LBB0_2\n    mvns r3, r3\n.LBB0_2:\n```\n\n### Impact\n\nThe exact impact is unclear, especially since `cmov` clearly warns users that the portable version is best-effort.",
  "id": "GHSA-2gqc-6j2q-83qp",
  "modified": "2026-01-23T21:46:10Z",
  "published": "2026-01-15T18:17:15Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/RustCrypto/utils/security/advisories/GHSA-2gqc-6j2q-83qp"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-23519"
    },
    {
      "type": "WEB",
      "url": "https://github.com/RustCrypto/utils/commit/55977257e7c82a309d5e8abfdd380a774f0f9778"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/RustCrypto/utils"
    },
    {
      "type": "WEB",
      "url": "https://rustsec.org/advisories/RUSTSEC-2026-0003.html"
    }
  ],
  "schema_version": "1.4.0",
  "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": "RustCrypto Utilities cmov: `thumbv6m-none-eabi` compiler emits non-constant time assembly when using `cmovnz`"
}



Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

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.

Loading…

Loading…

Loading…

Related by attack behaviour

Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.


Loading…