Listen to this Post
How GHSA-3gjw-f78c-vvpw Works
The vulnerability resides in the way `tokio-postgres` handles `DataRow` messages from a PostgreSQL server. During query execution, the server first sends a `RowDescription` message that declares the number of columns and their types. Later, for each row of data, the server sends a `DataRow` message containing the actual field values. The client library expects the number of fields in the `DataRow` to match the number of columns declared in the RowDescription.
However, a malicious or compromised server can send a `DataRow` that contains fewer fields than the number of columns advertised in the RowDescription. When the client application subsequently attempts to read one of the missing columns using Row::get, Row::try_get, SimpleQueryRow::get, or SimpleQueryRow::try_get, the library does not validate that the field count matches the column count. Instead, it uses the column index (derived from the RowDescription) to index into an internal `ranges` vector that was built from the actual `DataRow` field count. Because the `ranges` vector has fewer entries than the index requested, this operation causes an out‑of‑bounds panic, which aborts the calling task and leads to a denial of service.
Crucially, this panic occurs even when using the otherwise non‑panicking `try_get` methods – the panic happens before any error can be returned. The affected functions include Row::get, Row::try_get, SimpleQueryRow::get, and SimpleQueryRow::try_get. The issue is triggered solely by the server’s response, requiring no special client‑side input other than a normal query that expects a certain number of columns.
The attack vector is network‑based: an attacker who can control the database server (or intercept and modify the connection between the client and a trusted server) can craft a `DataRow` with fewer fields and cause the client to panic. This is particularly dangerous for applications that connect to untrusted or user‑supplied PostgreSQL instances, or where a man‑in‑the‑middle (MITM) can alter the wire protocol.
The root cause is a missing validation check when constructing the `Row` and `SimpleQueryRow` objects. The fix, introduced in commit 7a00ffa9ad4d951ec0a4564b52f1780fa9d353c1, adds an explicit comparison between the length of the `ranges` vector (derived from the DataRow) and the number of columns in the RowDescription. If they differ, the library now returns a recoverable `Error` of kind `InvalidData` instead of allowing a panic. The patched version `0.7.18` was released on 2026‑06‑12, and the GitHub Advisory was published on 2026‑08‑24.
DailyCVE Form:
Platform: tokio‑postgres (Rust)
Version: < 0.7.18
Vulnerability: Panic DoS (out‑of‑bounds)
Severity: Moderate (CVSS 6.9)
Date: 2026‑08‑24
Prediction: Already patched in v0.7.18 (2026‑06‑12)
What Undercode Say:
Check currently installed version cargo tree | grep tokio-postgres Upgrade to the patched version cargo update -p tokio-postgres --precise 0.7.18 Verify the fix is applied cargo tree | grep tokio-postgres
Rust code snippet to validate the fix (using the patched version):
use tokio_postgres::{NoTls, Error};
[tokio::main]
async fn main() -> Result<(), Error> {
// Connect to a trusted database (no exploit here)
let (client, connection) = tokio_postgres::connect(
"host=localhost user=postgres",
NoTls,
).await?;
tokio::spawn(async move {
if let Err(e) = connection.await {
eprintln!("Connection error: {}", e);
}
});
// A normal query that expects 2 columns
let rows = client.query("SELECT 1, 2", &[]).await?;
for row in rows {
let a: i32 = row.get(0);
let b: i32 = row.get(1);
println!("{} {}", a, b);
}
Ok(())
}
Exploit: (Educational Purposes!)
A malicious server (or MITM) can send a `DataRow` with fewer fields than advertised. For example, if the `RowDescription` declares 2 columns, the server sends a `DataRow` with only 1 field. The client will panic when attempting to access the second column:
// Hypothetical server-side pseudocode (for illustration only)
fn send_malicious_data_row() {
// Send RowDescription with 2 columns
send_row_description(2);
// Send DataRow with only 1 field
send_data_row(vec![b"value"]);
}
On the client side, the following code would panic:
let rows = client.query("SELECT 1, 2", &[]).await?;
for row in rows {
let a: i32 = row.get(0); // OK
let b: i32 = row.get(1); // PANIC: index out of bounds
}
Protection from this CVE:
- Upgrade to `tokio-postgres` version 0.7.18 or later immediately.
- If an immediate upgrade is not possible, validate that your application only connects to trusted database servers that you control and that are not subject to MITM attacks.
- Monitor your database connections for unexpected `DataRow` field counts (e.g., by logging row metadata) as a detection measure.
- Apply the official patch (commit
7a00ffa) if you are maintaining a fork of the library. - Consider using a connection pool or retry logic that can recover from task aborts, though this is a workaround and not a complete fix.
Impact:
- Denial of Service: A single malicious `DataRow` can panic and abort the calling task, causing the client to crash or become unresponsive. In multi‑threaded or async environments, this can bring down the entire service if the panic is not caught (and Rust panics are not recoverable in a safe way).
- Scope: Applications that connect to untrusted PostgreSQL servers, user‑supplied databases, or where the network path is insecure are at highest risk. Even `try_get` methods are vulnerable, so no safe API exists in affected versions.
- CVSS Score: 6.9 (Medium) – Network exploitable, low attack complexity, no privileges required, and low availability impact.
- Affected Versions: All `tokio-postgres` releases prior to 0.7.18 (including 0.7.17 and earlier).
- Fixed Version: 0.7.18 (released 2026‑06‑12). The fix ensures that a mismatched field count results in a recoverable `Error` instead of a panic.
🎯Let’s Practice Exploiting & Learn Patching For Free:
🎓 Live Courses & Certifications:
Join Undercode Academy for Verified Certifications
🚀 Request a Custom Project:
Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

