CVE-2026-24850: Ml dsa ML-DSA Signature Verification Accepts Signatures Vulnerability
MODERATECVE-2026-24850 is a MODERATE (CVSS 5.3) ml-dsa signature verification accepts signatures vulnerability (CWE-347: Improper Verification of Cryptographic Signature) affecting Ml dsa libraries in the crates.io ecosystem. The issue involves ml-dsa signature verification accepts signatures with repeated hint indices. Remediation is available by upgrading affected packages to version 0.1.0-rc.4.
CVE-2026-24850 at a Glance
Security Impact
CVSS: 5.3
The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N).
How to Fix CVE-2026-24850
To remediate this vulnerability, upgrade all affected Ml dsa dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.
Upgrade ml-dsa to 0.1.0-rc.4
Run the following command in your project directory to verify that all resolved dependencies use the patched release:
inspect dependencies for ml-dsa
How to Check if You Are Affected
To determine whether your application is affected by CVE-2026-24850, inspect your project dependencies for Ml dsa:
inspect dependencies for ml-dsa
Analyze the terminal output to locate any version of Ml dsa in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 0.1.0-rc.4), your application is affected.
Note: Verify declared build manifests and deployed runtime container environments.
Technical Details
Vulnerability Mechanism & Technical Analysis
This vulnerability is classified under CWE-347: Improper Verification of Cryptographic Signature, where the product does not verify, or incorrectly verifies, the cryptographic signature for data. In Ml dsa, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.
Source Advisory Statement
CVE-2026-24850 Affected Ml dsa Versions
1 component(s)| Product / Package | Ecosystem | Affected Versions | Fixed Version |
|---|---|---|---|
|
ml-dsa
|
crates.io |
≥ 0.0.4
< 0.1.0-rc.4
|
0.1.0-rc.4
|
References
Frequently Asked Questions
What is CVE-2026-24850?
Which Ml dsa versions are affected?
What version fixes CVE-2026-24850?
Is ml-dsa affected?
What is the CVSS score of CVE-2026-24850?
What CWE is associated with CVE-2026-24850?
How can I check crates.io dependencies for CVE-2026-24850?
Machine-readable OSV JSON
OSV v1.5 Schema
{
"schema_version" : "1.4.0",
"id" : "GHSA-5x2r-hc65-25f9",
"modified" : "2026-01-28T16:44:47Z",
"published" : "2026-01-28T16:44:47Z",
"aliases" : [ "CVE-2026-24850" ],
"summary" : "ML-DSA Signature Verification Accepts Signatures with Repeated Hint Indices",
"details" : "**Affected Crate:** `ml-dsa` \n**Affected Versions:** v0.1.0-rc.2 (and commits since `b01c3b7`) \n**Severity:** Medium \n**Reporter:** Oren Yomtov (Fireblocks)\n\n## Summary\n\nThe ML-DSA signature verification implementation in the RustCrypto `ml-dsa` crate incorrectly accepts signatures with repeated (duplicate) hint indices. According to the ML-DSA specification (FIPS 204 / RFC 9881), hint indices within each polynomial must be **strictly increasing**. The current implementation uses a non-strict monotonic check (`<=` instead of `<`), allowing duplicate indices.\n\n**Note:** This is a regression bug. The original implementation was correct, but commit `b01c3b7` (\"Make ML-DSA signature decoding follow the spec (#895)\", fixing issue #894) inadvertently changed the strict `<` comparison to `<=`, introducing the vulnerability.\n\n## Vulnerability Details\n\n### Root Cause\n\nThe vulnerability is located in the `monotonic` helper function in `ml-dsa/src/hint.rs`:\n\n```rust\nfn monotonic(a: &[usize]) -> bool {\n a.iter().enumerate().all(|(i, x)| i == 0 || a[i - 1] <= *x)\n}\n```\n\nThe comparison operator `<=` allows equal consecutive values, meaning duplicate hint indices are not rejected. The correct implementation should use strict less-than (`<`):\n\n```rust\nfn monotonic(a: &[usize]) -> bool {\n a.iter().enumerate().all(|(i, x)| i == 0 || a[i - 1] < *x)\n}\n```\n\n### Regression Analysis\n\n- **Original correct code** (commit `1d3a1d1` - \"Add support for ML-DSA (#877)\"): Used `<` (strict)\n- **Bug introduced** (commit `b01c3b7` - \"Make ML-DSA signature decoding follow the spec (#895)\"): Changed to `<=`\n\nThe commit message suggests it was intended to fix issue #894 and make decoding follow the spec, but the change to the `monotonic` function was in the wrong direction. The other changes in that commit (to `use_hint` function) may have been correct, but this specific change introduced signature malleability.\n\n### Technical Impact\n\nThis vulnerability allows **signature malleability** - the same logical signature can have multiple valid byte-level encodings. An attacker can take a valid signature and create additional \"valid\" signatures by duplicating hint indices.\n\nPer the ML-DSA specification (FIPS 204, Section 6.2 and Algorithm 26 `HintBitUnpack`), hint indices must be strictly increasing to ensure a unique, canonical encoding. Accepting non-canonical signatures can lead to:\n\n1. **Signature Malleability:** Multiple distinct byte sequences verify as valid for the same message/key pair\n2. **Protocol-Level Vulnerabilities:** Systems that rely on signature uniqueness (e.g., for transaction deduplication, replay protection, or signature-based identifiers) may be vulnerable\n3. **Interoperability Issues:** Non-compliant signatures may be rejected by other conforming implementations\n\n### Affected Security Levels\n\nAll ML-DSA parameter sets are affected:\n- ML-DSA-44 (NIST Security Level 2)\n- ML-DSA-65 (NIST Security Level 3)\n- ML-DSA-87 (NIST Security Level 5)\n\n## Proof of Concept\n\nSee the file [`poc_mldsa_repeated_hint.rs`](https://gist.github.com/orenyomtov/fb4616eb77d33017f41a71b30aa41a04) for a standalone proof of concept that demonstrates the vulnerability.\n\nThe PoC uses test vectors from the Wycheproof test suite that specifically test for this invalid encoding:\n\n- **Test Vector Source:** [Wycheproof ML-DSA Test Vectors](https://github.com/C2SP/wycheproof/blob/master/testvectors_v1/mldsa_44_verify_test.json)\n- Test Case ID 18: \"signature with a repeated hint\"\n- Expected Result: `invalid`\n- Actual Result: `valid` (BUG)\n\n## Remediation\n\nUpdate the `monotonic` function in `ml-dsa/src/hint.rs` to use strict less-than comparison:\n\n```rust\nfn monotonic(a: &[usize]) -> bool {\n a.iter().enumerate().all(|(i, x)| i == 0 || a[i - 1] < *x)\n}\n```\n\n## Design Intent: ML-DSA is NOT Intended to Allow Malleability\n\nWhile some cryptographic libraries intentionally permit signature malleability for compatibility or performance reasons, **ML-DSA is explicitly designed to prevent it**:\n\n1. **FIPS 204 Specification:** ML-DSA is designed to be strongly unforgeable under chosen message attacks (SUF-CMA). This security property explicitly prevents signature malleability.\n\n2. **NIST PQC Forum Discussion:** In February 2024, there was a discussion on the NIST PQC forum about potential malleability in ML-DSA's hint unpacking. The consensus was that ML-DSA is intended to be SUF-CMA, meaning any malleability issues should be considered bugs and fixed.\n\n3. **No Documentation of Intentional Malleability:** There is no documentation in the RustCrypto `ml-dsa` crate, FIPS 204, or RFC 9881 suggesting that signature malleability is an acceptable or intentional property.\n\n4. **Regression Bug:** The fact that the original implementation had strict ordering (`<`) and this was changed to non-strict (`<=`) in a \"fix\" commit suggests this was an unintentional regression, not a design decision.",
"severity" : [ {
"type" : "CVSS_V3",
"score" : "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N"
} ],
"affected" : [ {
"package" : {
"ecosystem" : "crates.io",
"name" : "ml-dsa"
},
"ranges" : [ {
"type" : "ECOSYSTEM",
"events" : [ {
"introduced" : "0.0.4"
}, {
"fixed" : "0.1.0-rc.4"
} ]
} ]
} ],
"references" : [ {
"type" : "WEB",
"url" : "https://github.com/RustCrypto/signatures/security/advisories/GHSA-5x2r-hc65-25f9"
}, {
"type" : "ADVISORY",
"url" : "https://nvd.nist.gov/vuln/detail/CVE-2026-24850"
}, {
"type" : "WEB",
"url" : "https://github.com/RustCrypto/signatures/issues/894"
}, {
"type" : "WEB",
"url" : "https://github.com/RustCrypto/signatures/pull/895"
}, {
"type" : "WEB",
"url" : "https://github.com/RustCrypto/signatures/commit/400961412be2e2ab787942cf30e0a9b66b37a54a"
}, {
"type" : "WEB",
"url" : "https://github.com/RustCrypto/signatures/commit/b01c3b73dd08d0094e089aa234f78b6089ec1f38"
}, {
"type" : "WEB",
"url" : "https://csrc.nist.gov/pubs/fips/204/final"
}, {
"type" : "WEB",
"url" : "https://datatracker.ietf.org/doc/html/rfc9881"
}, {
"type" : "WEB",
"url" : "https://github.com/C2SP/wycheproof"
}, {
"type" : "WEB",
"url" : "https://github.com/C2SP/wycheproof/blob/master/testvectors_v1/mldsa_44_verify_test.json"
}, {
"type" : "WEB",
"url" : "https://github.com/C2SP/wycheproof/blob/master/testvectors_v1/mldsa_65_verify_test.json"
}, {
"type" : "WEB",
"url" : "https://github.com/C2SP/wycheproof/blob/master/testvectors_v1/mldsa_87_verify_test.json"
}, {
"type" : "PACKAGE",
"url" : "https://github.com/RustCrypto/signatures"
} ],
"database_specific" : {
"cwe_ids" : [ "CWE-347" ],
"severity" : "MODERATE",
"github_reviewed" : true,
"github_reviewed_at" : "2026-01-28T16:44:47Z",
"nvd_published_at" : "2026-01-28T01:16:15Z"
}
}