GHSA-ff9q-rm55-q7qr: Diesel async Diesel-async May Expose Uninitialized Padding Vulnerability

LOW
CWE-126
Published
Advisory Summary

GHSA-ff9q-rm55-q7qr is a LOW diesel-async may expose uninitialized padding vulnerability (CWE-126: Buffer Over-read) affecting Diesel async libraries in the crates.io ecosystem. The issue involves diesel-async may expose uninitialized padding bytes for mysql temporal columns. Remediation is available by upgrading affected packages to version 0.9.0.

GHSA-ff9q-rm55-q7qr at a Glance

CVE Identifier N/A
GHSA Identifier GHSA-ff9q-rm55-q7qr
Severity LOW
CVSS v3.1 Base Score N/A
CWE Classification CWE-126: Buffer Over-read
Affected Product Diesel async
Package Ecosystem crates.io
Published Date
Last Updated

How to Fix GHSA-ff9q-rm55-q7qr

To remediate this vulnerability, upgrade all affected Diesel async dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

diesel-async fixed: 0.9.0
Upgrade diesel-async to 0.9.0
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

inspect dependencies for diesel-async

How to Check if You Are Affected

To determine whether your application is affected by GHSA-ff9q-rm55-q7qr, inspect your project dependencies for Diesel async:

inspect dependencies for diesel-async

Analyze the terminal output to locate any version of Diesel async in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 0.9.0), 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-126: Buffer Over-read, where the product reads from a buffer using buffer access mechanisms such as indexes or pointers that reference memory locations after the targeted buffer. In Diesel async, 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

### Summary diesel-async exposes uninitialized stack padding to safe code on every read of a MySQL `DATE`, `TIME`, `DATETIME`, or `TIMESTAMP` column. Reading that buffer is undefined behavior, and the leaked bytes can contain stale heap/stack contents, so this is both a soundness bug and a potential information-disclosure vector. ### Details In `diesel-async/src/mysql/row.rs` (lines 65-103), `MysqlRow::get` builds a `MysqlTime` from the parsed `mysql_async::Value` and then fabricates the byte buffer that downstream `FromSql` impls expect like this: ```rust let date = MysqlTime::new(/* fields from Value::Date / Value::Time */); let buffer = unsafe { let ptr = &date as *const MysqlTime as *const u8; let slice = std::slice::from_raw_parts(ptr, std::mem::size_of::<MysqlTime>()); slice.to_vec() }; ``` `MysqlTime` is `#[repr(C)]` with 3 bytes of padding after `bool neg` (Linux x86_64, offsets 0x21..0x23). The literal construction leaves that padding uninitialized, and `to_vec()` carries it into a `Vec<u8>` that becomes the `MysqlValue`'s backing buffer, reachable from safe code via `MysqlValue::as_bytes() -> &[u8]`. `diesel` itself avoids this by going through `MaybeUninit::<MysqlTime>::zeroed()` + `ptr::copy_nonoverlapping` (see `diesel/src/mysql/value.rs:43-94`); the same pattern would fix this. Alternatively, write the bytes diesel's `FromSql` reads without round-tripping through a `MysqlTime` value. ### PoC `Cargo.toml`: ```toml [dependencies] diesel = { version = "~2.3.0", default-features = false, features = ["mysql_backend"] } diesel-async = { version = "=0.8.0", features = ["mysql"] } mysql_common = { version = "0.35", default-features = false } ``` `src/main.rs`: ```rust use diesel::row::{Field, Row}; use diesel_async::{AsyncConnectionCore, AsyncMysqlConnection}; use mysql_common::{constants::ColumnType, packets::Column, prelude::FromRow, value::Value}; type MysqlRow = <AsyncMysqlConnection as AsyncConnectionCore>::Row<'static, 'static>; fn main() { let cols = std::sync::Arc::from([Column::new(ColumnType::MYSQL_TYPE_DATE)]); let raw = mysql_common::row::new_row(vec![Value::Date(2024, 1, 1, 0, 0, 0, 0)], cols); let row: MysqlRow = FromRow::from_row(raw); let field = row.get(0).unwrap(); let bytes = field.value().unwrap().as_bytes(); let _: u64 = bytes.iter().map(|&b| b as u64).sum(); // UB: hits padding } ``` Miri output: ``` error: Undefined Behavior: reading memory at alloc844[0x21..0x22], but memory is uninitialized at [0x21..0x22], and this operation requires initialized memory --> src/main.rs:14:37 | 14 | let _: u64 = bytes.iter().map(|&b| b as u64).sum(); // UB: hits padding | ^ Undefined Behavior occurred here | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information = note: stack backtrace: 0: main::{closure#0} at src/main.rs:14:37: 14:38 1: std::iter::adapters::map::map_fold::<&u8, u64, u64, {closure@src/main.rs:14:35: 14:39}, {closure@<u64 as std::iter::Sum>::sum<std::iter::Map<std::slice::Iter<'_, u8>, {closure@src/main.rs:14:35: 14:39}>>::{closure#0}}>::{closure#0} at /home/paolobarbolini/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/iter/adapters/map.rs:88:28: 88:34 2: <std::slice::Iter<'_, u8> as std::iter::Iterator>::fold::<u64, {closure@std::iter::adapters::map::map_fold<&u8, u64, u64, {closure@src/main.rs:14:35: 14:39}, {closure@<u64 as std::iter::Sum>::sum<std::iter::Map<std::slice::Iter<'_, u8>, {closure@src/main.rs:14:35: 14:39}>>::{closure#0}}>::{closure#0}}> at /home/paolobarbolini/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/slice/iter/macros.rs:279:27: 279:85 3: <std::iter::Map<std::slice::Iter<'_, u8>, {closure@src/main.rs:14:35: 14:39}> as std::iter::Iterator>::fold::<u64, {closure@<u64 as std::iter::Sum>::sum<std::iter::Map<std::slice::Iter<'_, u8>, {closure@src/main.rs:14:35: 14:39}>>::{closure#0}}> at /home/paolobarbolini/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/iter/adapters/map.rs:128:9: 128:50 4: <u64 as std::iter::Sum>::sum::<std::iter::Map<std::slice::Iter<'_, u8>, {closure@src/main.rs:14:35: 14:39}>> at /home/paolobarbolini/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/iter/traits/accum.rs:52:17: 56:18 5: <std::iter::Map<std::slice::Iter<'_, u8>, {closure@src/main.rs:14:35: 14:39}> as std::iter::Iterator>::sum::<u64> at /home/paolobarbolini/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/iter/traits/iterator.rs:3676:9: 3676:23 6: main at src/main.rs:14:18: 14:55 Uninitialized memory occurred at alloc844[0x21..0x22], in this allocation: alloc844 (Rust heap, size: 48, align: 1) { 0x00 │ e8 07 00 00 01 00 00 00 01 00 00 00 00 00 00 00 │ ................ 0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x20 │ 00 __ __ __ 01 00 00 00 00 00 00 00 __ __ __ __ │ .░░░........░░░░ } ``` ### Impact Soundness bug in safe API surface of `diesel-async`'s MySQL backend. Affects every user of `AsyncMysqlConnection` whose queries return a temporal column. AI disclosure: this issue was found via Claude Code running Claude Opus 4.7.

GHSA-ff9q-rm55-q7qr Affected Diesel async Versions

1 component(s)
Fixed Versions:
0.9.0
Product / Package Ecosystem Affected Versions Fixed Version
diesel-async
crates.io
≥ 0.1.0
< 0.9.0
0.9.0

References

Frequently Asked Questions

What is GHSA-ff9q-rm55-q7qr?
GHSA-ff9q-rm55-q7qr is a security vulnerability in Diesel async involving diesel-async may expose uninitialized padding bytes for MySQL temporal columns under CWE-126: Buffer Over-read.
Which Diesel async versions are affected?
Affected versions include releases prior to 0.9.0 across affected packages: diesel-async.
What version fixes GHSA-ff9q-rm55-q7qr?
Upgrading to 0.9.0 (or the latest patched release for your respective branch) resolves the vulnerability.
Is diesel-async affected?
Yes, diesel-async is affected in releases prior to 0.9.0. Upgrade your dependency to 0.9.0 or later.
What CWE is associated with GHSA-ff9q-rm55-q7qr?
GHSA-ff9q-rm55-q7qr is classified under CWE-126: Buffer Over-read (The product reads from a buffer using buffer access mechanisms such as indexes or pointers that reference memory locations after the targeted buffer.).
How can I check crates.io dependencies for GHSA-ff9q-rm55-q7qr?
Run the dependency tree command: 'inspect dependencies for diesel-async'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-ff9q-rm55-q7qr",
  "modified" : "2026-05-07T00:02:22Z",
  "published" : "2026-05-07T00:02:22Z",
  "aliases" : [ ],
  "summary" : "diesel-async may expose uninitialized padding bytes for MySQL temporal columns",
  "details" : "### Summary\n\ndiesel-async exposes uninitialized stack padding to safe code on every read of a MySQL `DATE`, `TIME`, `DATETIME`, or `TIMESTAMP` column. Reading that buffer is undefined behavior, and the leaked bytes can contain stale heap/stack contents, so this is both a soundness bug and a potential information-disclosure vector.\n\n### Details\n\nIn `diesel-async/src/mysql/row.rs` (lines 65-103), `MysqlRow::get` builds a `MysqlTime` from the parsed `mysql_async::Value` and then fabricates the byte buffer that downstream `FromSql` impls expect like this:\n\n```rust\nlet date = MysqlTime::new(/* fields from Value::Date / Value::Time */);\nlet buffer = unsafe {\n    let ptr = &date as *const MysqlTime as *const u8;\n    let slice = std::slice::from_raw_parts(ptr, std::mem::size_of::<MysqlTime>());\n    slice.to_vec()\n};\n```\n\n`MysqlTime` is `#[repr(C)]` with 3 bytes of padding after `bool neg` (Linux x86_64, offsets 0x21..0x23). The literal construction leaves that padding uninitialized, and `to_vec()` carries it into a `Vec<u8>` that becomes the `MysqlValue`'s backing buffer, reachable from safe code via `MysqlValue::as_bytes() -> &[u8]`.\n\n`diesel` itself avoids this by going through `MaybeUninit::<MysqlTime>::zeroed()` + `ptr::copy_nonoverlapping` (see `diesel/src/mysql/value.rs:43-94`); the same pattern would fix this. Alternatively, write the bytes diesel's `FromSql` reads without round-tripping through a `MysqlTime` value.\n\n### PoC\n\n`Cargo.toml`:\n```toml\n[dependencies]\ndiesel = { version = \"~2.3.0\", default-features = false, features = [\"mysql_backend\"] }\ndiesel-async = { version = \"=0.8.0\", features = [\"mysql\"] }\nmysql_common = { version = \"0.35\", default-features = false }\n```\n\n`src/main.rs`:\n```rust\nuse diesel::row::{Field, Row};\nuse diesel_async::{AsyncConnectionCore, AsyncMysqlConnection};\nuse mysql_common::{constants::ColumnType, packets::Column, prelude::FromRow, value::Value};\n\ntype MysqlRow = <AsyncMysqlConnection as AsyncConnectionCore>::Row<'static, 'static>;\n\nfn main() {\n    let cols = std::sync::Arc::from([Column::new(ColumnType::MYSQL_TYPE_DATE)]);\n    let raw = mysql_common::row::new_row(vec![Value::Date(2024, 1, 1, 0, 0, 0, 0)], cols);\n    let row: MysqlRow = FromRow::from_row(raw);\n\n    let field = row.get(0).unwrap();\n    let bytes = field.value().unwrap().as_bytes();\n    let _: u64 = bytes.iter().map(|&b| b as u64).sum(); // UB: hits padding\n}\n```\n\nMiri output:\n\n```\nerror: Undefined Behavior: reading memory at alloc844[0x21..0x22], but memory is uninitialized at [0x21..0x22], and this operation requires initialized memory\n  --> src/main.rs:14:37\n   |\n14 |     let _: u64 = bytes.iter().map(|&b| b as u64).sum(); // UB: hits padding\n   |                                     ^ Undefined Behavior occurred here\n   |\n   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior\n   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information\n   = note: stack backtrace:\n           0: main::{closure#0}\n               at src/main.rs:14:37: 14:38\n           1: std::iter::adapters::map::map_fold::<&u8, u64, u64, {closure@src/main.rs:14:35: 14:39}, {closure@<u64 as std::iter::Sum>::sum<std::iter::Map<std::slice::Iter<'_, u8>, {closure@src/main.rs:14:35: 14:39}>>::{closure#0}}>::{closure#0}\n               at /home/paolobarbolini/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/iter/adapters/map.rs:88:28: 88:34\n           2: <std::slice::Iter<'_, u8> as std::iter::Iterator>::fold::<u64, {closure@std::iter::adapters::map::map_fold<&u8, u64, u64, {closure@src/main.rs:14:35: 14:39}, {closure@<u64 as std::iter::Sum>::sum<std::iter::Map<std::slice::Iter<'_, u8>, {closure@src/main.rs:14:35: 14:39}>>::{closure#0}}>::{closure#0}}>\n               at /home/paolobarbolini/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/slice/iter/macros.rs:279:27: 279:85\n           3: <std::iter::Map<std::slice::Iter<'_, u8>, {closure@src/main.rs:14:35: 14:39}> as std::iter::Iterator>::fold::<u64, {closure@<u64 as std::iter::Sum>::sum<std::iter::Map<std::slice::Iter<'_, u8>, {closure@src/main.rs:14:35: 14:39}>>::{closure#0}}>\n               at /home/paolobarbolini/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/iter/adapters/map.rs:128:9: 128:50\n           4: <u64 as std::iter::Sum>::sum::<std::iter::Map<std::slice::Iter<'_, u8>, {closure@src/main.rs:14:35: 14:39}>>\n               at /home/paolobarbolini/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/iter/traits/accum.rs:52:17: 56:18\n           5: <std::iter::Map<std::slice::Iter<'_, u8>, {closure@src/main.rs:14:35: 14:39}> as std::iter::Iterator>::sum::<u64>\n               at /home/paolobarbolini/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/iter/traits/iterator.rs:3676:9: 3676:23\n           6: main\n               at src/main.rs:14:18: 14:55\n\nUninitialized memory occurred at alloc844[0x21..0x22], in this allocation:\nalloc844 (Rust heap, size: 48, align: 1) {\n    0x00 │ e8 07 00 00 01 00 00 00 01 00 00 00 00 00 00 00 │ ................\n    0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................\n    0x20 │ 00 __ __ __ 01 00 00 00 00 00 00 00 __ __ __ __ │ .░░░........░░░░\n}\n```\n\n### Impact\n\nSoundness bug in safe API surface of `diesel-async`'s MySQL backend. Affects every user of `AsyncMysqlConnection` whose queries return a temporal column.\n\nAI disclosure: this issue was found via Claude Code running Claude Opus 4.7.",
  "severity" : [ {
    "type" : "CVSS_V4",
    "score" : "CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:N/VC:L/VI:N/VA:L/SC:N/SI:N/SA:N/E:P"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "crates.io",
      "name" : "diesel-async"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "0.1.0"
      }, {
        "fixed" : "0.9.0"
      } ]
    } ]
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/diesel-rs/diesel_async/security/advisories/GHSA-ff9q-rm55-q7qr"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/diesel-rs/diesel_async/commit/18f2c861c51b4a5f23a20bd749eba13737b9e4aa"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/diesel-rs/diesel_async"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-126" ],
    "severity" : "LOW",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-05-07T00:02:22Z",
    "nvd_published_at" : null
  }
}