diff --git a/crates/auto_vec/RUSTSEC-2026-0133.md b/crates/auto_vec/RUSTSEC-2026-0133.md index 057530fc2d..5583319327 100644 --- a/crates/auto_vec/RUSTSEC-2026-0133.md +++ b/crates/auto_vec/RUSTSEC-2026-0133.md @@ -4,20 +4,24 @@ id = "RUSTSEC-2026-0133" package = "auto_vec" date = "2026-05-02" url = "https://github.com/lluvz/AutoVec/issues/1" -informational = "unsound" categories = ["memory-corruption"] keywords = ["out-of-bounds", "pointer-arithmetic"] +[affected.functions] +"auto_vec::AutoVec::iter" = [">=0.1.4"] +"auto_vec::AutoVec::iter_mut" = [">=0.1.4"] + [versions] patched = [] ``` -# Invalid pointer arithmetic in `iter()` and `iter_mut()` +# Out-of-bounds access due to pointer arithmetic bug in `iter()` and `iter_mut()` The `iter()` and `iter_mut()` APIs compute `current = (&children[0] as *const *const RawAutoChild).sub(1)`, which -performs pointer subtraction going before the start of the allocation. This -is undefined behavior per Rust's pointer arithmetic rules. +performs a pointer subtraction that returns a result before the start of the +allocation. This is immediate undefined behavior as per the safety contract of +the `sub` method on pointers, and subsequently results in out-of-bounds access. -This can be triggered through safe public APIs — `iter()` and `iter_mut()` -— with no `unsafe` required from the caller. +This can be triggered without the use of unsafe code via the `iter()` and +`iter_mut()` methods on `AutoVec`. diff --git a/crates/bitchomp/RUSTSEC-2026-0131.md b/crates/bitchomp/RUSTSEC-2026-0131.md index 9b7d49a3f1..7533edc161 100644 --- a/crates/bitchomp/RUSTSEC-2026-0131.md +++ b/crates/bitchomp/RUSTSEC-2026-0131.md @@ -8,17 +8,20 @@ informational = "unsound" categories = ["memory-corruption"] keywords = ["double-free"] +[affected.functions] +"bitchomp::Chomp::inner" = [">=0.2.8"] + [versions] patched = [] ``` # Double-free in `Chomp::inner()` -`Chomp::inner()` uses `std::ptr::read_unaligned` to move out the value from a -raw pointer. If the original value is an owned type (e.g. `Box`), calling -`inner()` moves out the ownership, but the original variable will still be -dropped at the end of its scope. This causes the same heap memory to be freed -twice, resulting in a double-free and undefined behavior. +`Chomp::inner` uses `std::ptr::read_unaligned` to move out the value behind +a raw pointer, thereby performing a copy without inhibiting the destructor of +the original value, which is unsound for types that do not implement the `Copy` +trait (which there isn't a trait bound for). If the value is of a type with +a destructor that frees memory, such as `Box`, this results in a double-free. -This can be triggered through safe public APIs — `Chomp::new()` and -`Chomp::inner()` — with no `unsafe` required from the caller. +This can be triggered without the use of unsafe code through the safe public +methods `Chomp::new` and `Chomp::inner`. diff --git a/crates/caja/RUSTSEC-2026-0130.md b/crates/caja/RUSTSEC-2026-0130.md index 8f9bcd8204..4a79d248b4 100644 --- a/crates/caja/RUSTSEC-2026-0130.md +++ b/crates/caja/RUSTSEC-2026-0130.md @@ -8,17 +8,20 @@ informational = "unsound" categories = ["memory-corruption"] keywords = ["out-of-bounds"] +[affected.functions] +"caja::Caja::Index::index" = [">=0.1.0"] +"caja::Caja::Index::index_mut" = [">=0.1.0"] + [versions] patched = [">= 0.3.0"] ``` -# Out-of-bounds read/write in `Index` and `IndexMut` implementations +# Out-of-bounds access in `Index` and `IndexMut` implementations -The `Index` and `IndexMut` implementations for `Caja` use unchecked pointer -arithmetic without bounds validation. Creating a `Caja` with a small key and -then accessing an out-of-range index causes out-of-bounds reads or writes -beyond the allocated memory. +The `Index` and `IndexMut` implementations for `Caja` use pointer arithmetic +without any bounds checking. Creating a `Caja` with a small key and then +accessing an out-of-range index allows accesses beyond beyond the bounds of the +allocated memory. -This can be triggered through safe public APIs — the `[]` indexing operator -on a `Caja` with an out-of-range index — with no `unsafe` required from the -caller. +This can be triggered without the use of unsafe code via the `[]` indexing +operator. diff --git a/crates/dahl-salso/RUSTSEC-2026-0129.md b/crates/dahl-salso/RUSTSEC-2026-0129.md index c723694a16..5c8902d87f 100644 --- a/crates/dahl-salso/RUSTSEC-2026-0129.md +++ b/crates/dahl-salso/RUSTSEC-2026-0129.md @@ -8,22 +8,24 @@ informational = "unsound" categories = ["memory-corruption"] keywords = ["out-of-bounds", "buffer-overflow"] +[affected.functions] +"dahl_salso::clustering::Clusterings::from_i32_column_major_order" = [">= 0.5.0", "< 0.6.8"] + [versions] patched = [">= 0.6.8"] ``` -# Buffer overflow in `Clusterings::from_i32_column_major_order()` +# Buffer overflow in `Clusterings::from_i32_column_major_order` The `from_i32_column_major_order` method can create inconsistent internal state. When `labels` length and `n_items` mismatch, `n_clusterings` becomes -`labels.len() / n_items` (truncated), but subsequent calls to `label()` use +`labels.len() / n_items` (truncated), but subsequent calls to `label` use indices that exceed the internal data bounds, causing a buffer overflow. -For example, `Clusterings::from_i32_column_major_order(&[1,2,3,4,5], 3)` -creates clusterings with `n_clusterings = 5/3 = 1`. Then -`clusterings.label(1, 0)` accesses index `1*3 = 3`, but only 3 elements -exist (indices 0,1,2), causing out-of-bounds access. +For example, `Clusterings::from_i32_column_major_order(&[1,2,3,4,5], 3)` creates +clusterings with `n_clusterings = 5/3 = 1`. Then `clusterings.label(1, 0)` +accesses index `1*3 = 3`, but only 3 elements exist (indices 0,1,2), causing +out-of-bounds access. -This can be triggered through safe public APIs — -`from_i32_column_major_order()` and `label()` — with no `unsafe` required -from the caller. +This can be triggered without the use of unsafe code through the safe public +methods `Clusterings::from_i32_column_major_order` and `Clusterings::label`. diff --git a/crates/diesel-async/RUSTSEC-2026-0138.md b/crates/diesel-async/RUSTSEC-2026-0138.md index 7b247374ac..4f823bf474 100644 --- a/crates/diesel-async/RUSTSEC-2026-0138.md +++ b/crates/diesel-async/RUSTSEC-2026-0138.md @@ -4,32 +4,39 @@ id = "RUSTSEC-2026-0138" package = "diesel-async" date = "2026-04-30" url = "https://github.com/diesel-rs/diesel_async/security/advisories/GHSA-ff9q-rm55-q7qr" +aliases = ["GHSA-ff9q-rm55-q7qr"] informational = "unsound" [versions] patched = [">= 0.9.0"] ``` -# Unsound access to padding bytes while serializing date/time values using the Mysql backend +# Unsound access to padding bytes while deserializing date/time values using the MySQL backend -Diesel-async uses the mysql-async crate for interacting with Mysql compatible databases. This library already provides access to deserialized data for date/time releated types. Diesel-async then translated these deserialized data back to their serialized binary representation to hook into diesels desearialization framework. +`diesel-async` uses the `mysql-async` crate for interacting with +MySQL-compatible databases. This library already provides access to deserialized +data for date/time releated types. `diesel-async` then translates this +deserialized data back to its serialized binary representation to interoperate +with Diesel's deserialization framework. -While serializing these data/time values again Diesel-async relied on a cast between the `MysqlTime` `#[repr(C)]` struct (defined by Diesel) and a byte array. As this cast exposes padding bytes contained in this struct, this is undefined behaviour. +While serializing these data/time values, `diesel-async` relied on a cast +between the `#[repr(C)]`-annotated struct `MysqlTime` (defined by Diesel) and +a byte array. This cast created a reference to padding bytes contained in this +struct, which is undefined behavior. -This vulnerability affects any user deserializing date/time values using the Mysql backend and diesel-async. +The following trait implementations in the `diesel` crate are affected: +- `deserialize::FromSql` +- `deserialize::FromSql` +- `deserialize::FromSql` +- `deserialize::FromSql` -This affects any usage of the following functions with a `AsyncMysqlConnection` provided by diesel-async: - -* `diesel::serialize::FromSql` -* `diesel::serialize::FromSql` -* `diesel::serialize::FromSql` -* `diesel::serialize::FromSql` - - -## Mitigation - -The preferred mitigation to the outlined problem is to update to Diesel-async version 0.9.0 or newer, which includes fixes for the problem. +## Impact +This unsoundness is accessible to any user deserializing date/time values using +the MySQL backend and `diesel-async`. Note that, in the current version of Rust, +this undefined behavior does not lead to any security issues, and no threat to +existing deployments is posed by it. ## Resolution - -Diesel-async now just calls a safe serialization method provided by Diesel 2.3.9 and newer +This unsoundness is fixed in `diesel-async` 0.9.0, which corresponds to `diesel` +2.3.9, by serializing the data without materializing references to struct +padding. diff --git a/crates/diesel/RUSTSEC-2026-0111.md b/crates/diesel/RUSTSEC-2026-0111.md index 6957d2b678..3971c81bce 100644 --- a/crates/diesel/RUSTSEC-2026-0111.md +++ b/crates/diesel/RUSTSEC-2026-0111.md @@ -4,26 +4,30 @@ id = "RUSTSEC-2026-0111" package = "diesel" date = "2026-04-24" url = "https://github.com/diesel-rs/diesel/pull/5042" -informational = "unsound" aliases = ["GHSA-h5x4-m2qf-r4f2"] +informational = "unsound" [affected.functions] -"diesel::sqlite::SqliteValue::read_str" = ["<2.3.8"] -"diesel::deserialize::FromSql::::from_sql" = ["<2.3.8"] +"diesel::sqlite::SqliteValue::read_str" = ["< 2.3.8"] +"diesel::deserialize::FromSql::::from_sql" = ["< 2.3.8"] [versions] patched = [">= 2.3.8"] ``` -# Possible UTF-8 corruption in Diesels SQLite backend - -Diesel uses the `sqlite3_value_text` function to receive strings from SQLite while deserializing query results. We misinterpreted the corresponding [SQLite](https://sqlite.org/c3ref/value_blob.html) documentation that this function always returns a UTF-8 encoded string values as `*const c_char`. Based on that we used `str::from_utf8_unchecked` to construct a Rust string slice without any additional UTF-8 checks in place. It turned out that this function doesn't always return correct UTF-8 strings. For field of the SQLite side storage type `BLOB` this pointer can contain arbitrary bytes, which makes the usage of `str::from_utf8_unchecked` unsound as this violates the safety contract of `str` to only contain valid UTF-8 encoded Strings. +# Possible UTF-8 corruption in the SQLite backend -## Mitigation - -The preferred mitigation to the outlined problem is to update to a Diesel version 2.3.8 or newer, which includes fixes for the problem. +Diesel uses the `sqlite3_value_text` function to receive strings from +SQLite while deserializing query results. The [corresponding SQLite +documentation](https://sqlite.org/c3ref/value_blob.html) was misinterpreted +as saying that the function always returns a UTF-8 encoded string values as +`*const c_char`. Based on that assumption, `str::from_utf8_unchecked` was used +to construct a Rust string slice without any additional UTF-8 checks. It turned +out that this function doesn't always return correct UTF-8 strings: for field +of the SQLite side storage type `BLOB` this pointer can contain arbitrary bytes, +which makes the usage of `str::from_utf8_unchecked` violate the safety contract +of `str` to only contain valid UTF-8. ## Resolution - -Diesel now correctly checks whether the provides byte buffer is actually valid UTF-8, instead of relying on SQLite's documentation. This fix is included in the `2.3.8` release. +The necessary UTF-8 validity check was added in Diesel 2.3.8. diff --git a/crates/diesel/RUSTSEC-2026-0134.md b/crates/diesel/RUSTSEC-2026-0134.md index 08b6015299..4af02393ef 100644 --- a/crates/diesel/RUSTSEC-2026-0134.md +++ b/crates/diesel/RUSTSEC-2026-0134.md @@ -7,28 +7,32 @@ url = "https://github.com/diesel-rs/diesel/pull/5042" informational = "unsound" [affected.functions] -"diesel::serialize::ToSql" = ["<2.3.8"] -"diesel::serialize::ToSql" = ["<2.3.8"] -"diesel::serialize::ToSql" = ["<2.3.8"] -"diesel::serialize::ToSql" = ["<2.3.8"] - +"diesel::serialize::ToSql" = ["< 2.3.8"] +"diesel::serialize::ToSql" = ["< 2.3.8"] +"diesel::serialize::ToSql" = ["< 2.3.8"] +"diesel::serialize::ToSql" = ["< 2.3.8"] [versions] patched = [">= 2.3.8"] ``` -# Unsound access to padding bytes while serializing date/time values using the Mysql backend - -Diesel relies on libmysqlclient for interacting with Mysql compatible databases. This library requires to provide date/time values according to the byte layout of their `MYSQL_TIME` type. +# Unsound access to padding bytes while serializing date/time values using the MySQL backend -Diesel replicated this type as `#[repr(C)]` struct, populated all the fields of this struct and then casted this value to an array of bytes. As this cast exposes padding bytes contained in this struct, this is undefined behaviour. +Diesel relies on `libmysqlclient` for interacting with MySQL-compatible +databases. This library takes in date/time values according to the byte layout +of the `MYSQL_TIME` type. -This vulnerability affects any user serializing date/time values using the Mysql backend. +Diesel defined this type as a `#[repr(C)]` struct, populated all the fields of +this struct and then casted the value to an array of bytes. This cast created +a reference to padding bytes contained in this struct, which is undefined +behavior. -## Mitigation - -The preferred mitigation to the outlined problem is to update to Diesel version 2.3.8 or newer, which includes fixes for the problem. +## Impact +This unsoundness is accessible to any user serializing date/time values using +the MySQL backend. Note that, in the current version of Rust, this undefined +behavior does not lead to any security issues, and no threat to existing +deployments is posed by it. ## Resolution - -Diesel now manually serializes the relevant data without accessing the padding bytes. +Diesel 2.3.8 serializes the relevant data without materializing references to +struct padding. diff --git a/crates/diesel/RUSTSEC-2026-0135.md b/crates/diesel/RUSTSEC-2026-0135.md index da612ccfb5..8b80dfabee 100644 --- a/crates/diesel/RUSTSEC-2026-0135.md +++ b/crates/diesel/RUSTSEC-2026-0135.md @@ -9,23 +9,27 @@ informational = "unsound" [affected.functions] "diesel::debug_query" = ["<2.3.8"] - [versions] -patched = [">= 2.3.8"] +patched = [">=2.3.8"] ``` -# Unsound transmute while debug/display printing batch Insert statements in Diesel's SQLite backend - -Diesel allows users to output the generated SQL for any query DSL construct via th `diesel::debug_query` function as `Display` and `Debug` output. +# Unsound transmute while formatting batch `INSERT` statements in the SQLite backend -For the particular implementation used by batch Insert statements in the SQLite backend Diesel relied on an unspecified transmute between types with a `#[repr(rust)]` layout. This is formally undefined behaviour as the compiler is free to change the layout of these types at any time. +Diesel allows users to output the generated SQL for any query DSL construct via +the `diesel::debug_query` function using the `Debug` and `Display` traits. -This vulnerability affects users that print out batch insert statements constructed using an array/vector of values without default values using `diesel::debug_query` on the SQLite backend. +For the particular implementation used by batch `INSERT` statements in the SQLite +backend, an invalid transmute between types with a `#[repr(Rust)]` layout was +used, which is undefined behavior, as the compiler is free to change the layout +of these types at any time. -## Mitigation - -The preferred mitigation to the outlined problem is to update to Diesel version 2.3.8 or newer, which includes fixes for the problem. +## Impact +This unsoundness in invoked by users that print out batch `INSERT` statements +constructed using an array/vector of values without default values using +`diesel::debug_query` on the SQLite backend. Note that this class of undefined +behavior is not exploited by the current version of Rust and does not pose a +security threat to existing deployments. Only with `-Z randomize-layout` can +this error be observed. ## Resolution - -Diesel now uses a sound cast instead. +Diesel 2.3.8 replaces the transmute with a correct cast. diff --git a/crates/diesel/RUSTSEC-2026-0136.md b/crates/diesel/RUSTSEC-2026-0136.md index 4e12100c19..0be09b795a 100644 --- a/crates/diesel/RUSTSEC-2026-0136.md +++ b/crates/diesel/RUSTSEC-2026-0136.md @@ -17,23 +17,23 @@ categories = ["format-injection"] "diesel::pg::CopyFromQuery::with_escape" = ["<2.3.8"] "diesel::pg::CopyFromQuery::with_default" = ["<2.3.8"] - [versions] patched = [">= 2.3.8"] ``` # Command injection in Diesel's implementation of `COPY FROM`/`COPY TO` -Diesel allows users to configure various options for PostgreSQL's `COPY FROM` and `COPY TO` statements. These configurations are partially provided as strings or characters. - -Diesel did not check if any these user-provided options contain a quote character `'`, which can lead to the injection of additional options in the current `COPY FROM`/`COPY TO` statement. - -This vulnerability affects any user of `COPY FROM`/`COPY TO` that passes user-provided input to any of the affected functions. It can result in modifications of options in the current statement, but it is not possible inject additional statements. +Diesel allows users to configure various options for PostgreSQL's `COPY FROM` +and `COPY TO` statements. These configurations are partially provided as strings +or characters. Diesel did not check if any these user-provided options contain +a quote character `'`, which can lead to the injection of additional options in +the current `COPY FROM`/`COPY TO` statement. -## Mitigation - -The preferred mitigation to the outlined problem is to update to Diesel version 2.3.8 or newer, which includes fixes for the problem. +## Impact +This vulnerability affects any user of `COPY FROM`/`COPY TO` that passes +user-provided input to any of the affected functions. It can result in +modifications of options in the current statement, but it is not possible inject +additional statements. ## Resolution - -Diesel now correctly escapes any quotes contained in the provided arguments. +Diesel 2.3.8 correctly escapes any quotes contained in the provided arguments. diff --git a/crates/diesel/RUSTSEC-2026-0137.md b/crates/diesel/RUSTSEC-2026-0137.md index 048a94fe4e..052a174ba7 100644 --- a/crates/diesel/RUSTSEC-2026-0137.md +++ b/crates/diesel/RUSTSEC-2026-0137.md @@ -4,24 +4,35 @@ id = "RUSTSEC-2026-0137" package = "diesel" date = "2026-04-24" url = "https://github.com/diesel-rs/diesel/pull/5042" +informational = "unsound" [affected.functions] "diesel::sqlite::SqliteAggregate" = ["<2.3.8"] [versions] -patched = [">= 2.3.8"] +patched = [">=2.3.8"] ``` # Possible unaligned data access for implementations of `SqliteAggregate` -Diesel allows to register custom aggregate SQL functions for SQLite via the `SqliteAggregate` interface. - -To store an instance of the custom aggregate processor Diesel relied on the `sqlite3_aggregate_context` function provided by sqlite. This function doesn't provide any guarantees about alignment of the returned allocation, which in turn can lead to problems if the type implementing requires a special alignment, e.g. via a custom `#[align(x)]` attribute on the type implementing this trait. This affects any user of `SqliteAggregate` that registers the custom aggregate function with an SQLite connection, while using a non-standard alignment on the type implementing this trait. - -## Mitigation - -The preferred mitigation to the outlined problem is to update to a Diesel version 2.3.8 or newer, which includes fixes for the problem. +Diesel allows to register custom aggregate SQL functions for SQLite via the +`SqliteAggregate` interface. To store an instance of the custom aggregate +processor, Diesel relied on the `sqlite3_aggregate_context` function provided by +SQLite. This function provides no guarantees about the alignment of the returned +allocation, which leads to undefined behavior being subsequently invoked if the +type requires a alignment greater than what the memory allocator used by SQLite +provides, e.g. via a custom `#[align(x)]` attribute on the type implementing +this trait. + +## Impact +This unsoundness affects any user of `SqliteAggregate` that registers the +custom aggregate function with an SQLite connection, while using a non-standard +alignment on the type implementing this trait. It can cause violation of +alignment expectations of downstream unsafe code (such as when the low bits +of a pointer are used for tagging) or cause the compiler to emit SIMD load +instructions requiring alignment that access insufficiently aligned memory, +which crashes the program. ## Resolution - -Diesel now allocates the corresponding memory on Rust side to get a correctly aligned allocation. +Diesel 2.3.8 allocates the corresponding memory on the Rust side to get a +sufficiently aligned allocation. diff --git a/crates/emap/RUSTSEC-2026-0128.md b/crates/emap/RUSTSEC-2026-0128.md index 886ef0d35d..6d65e4cb6e 100644 --- a/crates/emap/RUSTSEC-2026-0128.md +++ b/crates/emap/RUSTSEC-2026-0128.md @@ -8,19 +8,31 @@ informational = "unsound" categories = ["memory-corruption"] keywords = ["double-free", "use-after-free"] +[affected.functions] +"emap::Keys::next" = [">=0.0.5"] + [versions] patched = [] ``` # Double-free and use-after-free in `Keys::next()` -`Keys::next()` uses `ptr::read` to move out the `Option` by value, which -drops the contained `V` when `V` is non-Copy (e.g. `String`). This leaves a -dangling value in the map's storage slot. Subsequent `get()` operations on -that key return a dangling reference to already-freed memory. +`Keys::next` uses `ptr::read` to access the map record by value, obtaining a +copy of an `Option`, which is unsound if `V` does not implement `Copy`. When +this `Option` is dropped, the destructor of the contained `V` is called, +which leaves a copy of a value whose destructor has already been called in the +map's storage slot. If `V` is a type that owns a heap allocation, such as `Box` +or `String`, subsequent `get` operations on that key can allow safe code to +obtain a dangling reference to memory that has already been freed. + +If `Map::keys` is called again and the iterator is traversed a second time, all +values have their destructors run once more, causing a double-free with an owned +`V`. + +Note that, as of version 0.0.13, dropping the map does not cause a double-free, +since its `Drop` implementation simply deallocates memory without calling the +destructors of the elements. -This can be triggered through safe public APIs — `Map::keys()`, -`Keys::next()`, and `Map::get()` — with no `unsafe` required from the -caller. Under Miri, accessing the freed slot produces "Undefined Behavior: -pointer not dereferenceable: alloc has been freed, so this pointer is -dangling". +This can be triggered without the use of unsafe code through the safe public +methods `Map::keys`, `Keys::next`, and `Map::get`. Miri diagnoses the undefined +behavior caused by this bug in `Map`. diff --git a/crates/libcrux-chacha20poly1305/RUSTSEC-2026-0124.md b/crates/libcrux-chacha20poly1305/RUSTSEC-2026-0124.md index 37766db41a..1155167539 100644 --- a/crates/libcrux-chacha20poly1305/RUSTSEC-2026-0124.md +++ b/crates/libcrux-chacha20poly1305/RUSTSEC-2026-0124.md @@ -3,10 +3,9 @@ id = "RUSTSEC-2026-0124" package = "libcrux-chacha20poly1305" date = "2026-03-29" - url = "https://github.com/cryspen/libcrux/pull/1386" - cvss = "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N" +categories = ["denial-of-service"] [affected.functions] "libcrux_chacha20poly1305::encrypt" = ["< 0.0.8"] @@ -16,7 +15,7 @@ cvss = "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N" patched = [">= 0.0.8"] ``` -# Potential Panic on Overlong Ciphertext Buffer +# Potential panic on overlong ciphertext buffer An application that passes in a ciphertext buffer of length greater than `ptxt.len() + TAG_LEN` to `libcrux_chacha20poly1305::encrypt` or diff --git a/crates/libcrux-ml-dsa/RUSTSEC-2026-0076.md b/crates/libcrux-ml-dsa/RUSTSEC-2026-0076.md index 2e53aea1af..5eef1abe6f 100644 --- a/crates/libcrux-ml-dsa/RUSTSEC-2026-0076.md +++ b/crates/libcrux-ml-dsa/RUSTSEC-2026-0076.md @@ -16,7 +16,7 @@ aliases = ["GHSA-xrf2-5r3p-5wgj"] patched = [">= 0.0.8 "] ``` -# Panic in Signature Hint Decoding During Verification +# Panic in signature hint decoding during verification During ML-DSA verification the serialized hint values are decoded as specified in algorithm 22 `HintBitUnpack` of [FIPS 204, subsection @@ -25,8 +25,8 @@ algorithm requires that the cumulative hint counters per row of the hint vector are strictly increasing and below a maximum value which depends on the choice of ML-DSA parameter set (line 4). -In libcrux-ml-dsa, hint decoding did not check the boundedness of the -cumulative hint counter of the last row of the hint vector. +In `libcrux-ml-dsa`, hint decoding did not check the boundedness of +the cumulative hint counter of the last row of the hint vector. ## Impact A manipulated invalid hint can cause an out-of-bounds memory access diff --git a/crates/libcrux-ml-dsa/RUSTSEC-2026-0077.md b/crates/libcrux-ml-dsa/RUSTSEC-2026-0077.md index d182f189f3..443b8efd0c 100644 --- a/crates/libcrux-ml-dsa/RUSTSEC-2026-0077.md +++ b/crates/libcrux-ml-dsa/RUSTSEC-2026-0077.md @@ -15,7 +15,7 @@ aliases = ["GHSA-cp57-fq8g-qh6v"] patched = [">= 0.0.8 "] ``` -# Incorrect Check of Signer Response Norm During Verification +# Incorrect check of signer response norm during verification The ML-DSA verification algorithm as specified in [FIPS 204, subsection @@ -25,13 +25,13 @@ signer response $z$ does not exceed $\gamma_1 - \beta$ (line 13 of Algorithm 8). The same check is required to be performed during signature generation. -libcrux-ml-dsa did not perform this check correctly during signature +`libcrux-ml-dsa` did not perform this check correctly during signature verification, accepting signatures with signer response norm above the allowed maximum value. The check is correctly performed during signing. ## Impact -Applications using libcrux-ml-dsa for signature verification would +Applications using `libcrux-ml-dsa` for signature verification would have accepted signatures that would be rejected by a conforming implementation. diff --git a/crates/libcrux-ml-dsa/RUSTSEC-2026-0125.md b/crates/libcrux-ml-dsa/RUSTSEC-2026-0125.md index 8d286171d8..592ea900ff 100644 --- a/crates/libcrux-ml-dsa/RUSTSEC-2026-0125.md +++ b/crates/libcrux-ml-dsa/RUSTSEC-2026-0125.md @@ -15,7 +15,7 @@ arch = ["x86_64"] patched = [">= 0.0.9"] ``` -# Signature Verification on AVX2 Platforms Mishandles Edge Case +# Signature verification on AVX2 platforms mishandles an edge case The AVX2 implementation of ML-DSA verification incorrectly implemented the `use_hint` function, mishandling an edge case that should lead to diff --git a/crates/libcrux-ml-dsa/RUSTSEC-2026-0126.md b/crates/libcrux-ml-dsa/RUSTSEC-2026-0126.md index 25203c11a9..e7a2a42cb7 100644 --- a/crates/libcrux-ml-dsa/RUSTSEC-2026-0126.md +++ b/crates/libcrux-ml-dsa/RUSTSEC-2026-0126.md @@ -15,7 +15,7 @@ arch = ["x86_64"] patched = [">= 0.0.9"] ``` -# AVX2 Implementation Did Not Fully Reduce Intermediate Values +# AVX2 implementation did not fully reduce intermediate values The AVX2 implementation of ML-DSA did not fully reduce intermediate inputs to the inverse NTT, which leads to a testable difference in diff --git a/crates/metacall/RUSTSEC-2026-0139.md b/crates/metacall/RUSTSEC-2026-0139.md index aac3cc0a60..91829b7964 100644 --- a/crates/metacall/RUSTSEC-2026-0139.md +++ b/crates/metacall/RUSTSEC-2026-0139.md @@ -8,24 +8,25 @@ informational = "unsound" categories = ["memory-corruption"] keywords = ["double-free", "null-pointer", "undefined-behavior"] +[affected.functions] +"metacall::MetaCallFuture::new_raw" = [">=0.4.0"] +"metacall::MetaCallPointer::clone" = [">=0.4.0"] + [versions] patched = [] ``` -# Null-pointer dereference and double-free via safe APIs - -Two soundness violations exist in the Rust bindings for MetaCall: - -**Null-pointer dereference:** `MetaCallFuture::new_raw()` accepts a raw -pointer without validation. The `Debug` impl calls `Box::from_raw(self.data)` -on it. Passing a null pointer causes the `Debug` impl to construct a -`NonNull` from null, producing undefined behavior. +# Null pointer dereference and double-free via safe APIs -**Double-free:** `MetaCallPointer::clone()` shares the same `rust_value` raw -pointer between the clone and the original. Calling `get_value_untyped()` on -both clones calls `Box::from_raw` on the same pointer twice, resulting in a -double-free. +The following two instances of undefined behavior exist in the `metacall` crate, which provides +Rust bindings for MetaCall: +- `MetaCallFuture::new_raw()` accepts a raw pointer without validation, which the `Debug` + implementation calls `Box::from_raw(self.data)` on, which is undefined behavior that results in + a null pointer being dereferenced. +- `MetaCallPointer::clone()` shares the same `rust_value` raw pointer between the clone and the + original. Calling `get_value_untyped()` on both clones calls `Box::from_raw` on the same pointer + a second time, resulting in a double-free. -Both issues can be triggered through safe public APIs — -`MetaCallFuture::new_raw()`, `MetaCallPointer::new()`, `clone()`, and -`get_value_untyped()` — with no `unsafe` required from the caller. +Both issues can be triggered without the use of unsafe code via the following public functions: +`MetaCallFuture::new_raw()`, `MetaCallPointer::new()`, `MetaCallPointer::clone()`, and +`MetaCallPointer::get_value_untyped()`.