GHSA-QWGH-2VCV-G2F7
Vulnerability from github – Published: 2026-08-19 19:15 – Updated: 2026-08-19 19:15
VLAI
Summary
block_buffer: panic corrupts inline buffer position
Details
Summary
A caught panic may leave the cursor position of EagerBuffer or ReadBuffer in a corrupted state; this in turn allows out-of-bounds reads/writes.
Details & PoC
The following two tests fail miri:
#[cfg(miri)]
#[test]
fn eager_digest_blocks_panic_corrupts_inline_position() {
// `EagerBuffer` stores its cursor in the last byte of the internal block.
// When `digest_blocks` completes a previously partial block, it overwrites
// that byte with input data before invoking the caller-provided `compress`
// callback. If the callback panics, safe code can catch the panic and keep
// using the buffer while its cursor byte no longer satisfies the internal
// `pos < block_size` invariant. Under Miri this `get_pos` call reaches the
// `unreachable_unchecked` used for the assumed-valid cursor.
let mut buf = EagerBuffer::<U4>::new(&[1, 2]);
let _ = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
buf.digest_blocks(&[3, 0xff], |_| panic!("simulated compression failure"));
}));
let _ = buf.get_pos();
}
#[cfg(miri)]
#[test]
fn read_buffer_generator_panic_corrupts_inline_position() {
// `ReadBuffer` stores its cursor in `buffer[0]`, but `write_block` gives
// `gen_block` mutable access to the whole internal block before restoring
// `buffer[0]` to a valid cursor. If `gen_block` writes an arbitrary first
// byte and panics, safe code can catch the panic and later observe an
// invalid cursor. Under Miri this `get_pos` call reaches the
// `unreachable_unchecked` used for the assumed-valid cursor.
let mut buf = ReadBuffer::<U4>::default();
let _ = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
buf.write_block(
1,
|block| {
block[0] = 0xff;
panic!("simulated block generation failure");
},
|_| {},
);
}));
let _ = buf.get_pos();
}
They fail on an unreachable_unchecked!() under the invariant for the pos to always be within bounds of the block.
Impact
While the byte that overwrites pos may come from untrusted input and is therefore attacker-controlled, this still relies on the surrounding code catching the panic and carrying on, which should be uncommon in practice.
For this to be exploitable, the attacker also needs a way to trigger a panic here; I have not investigated how feasible that is.
Credits
The issue was discovered by GPT-5.5
Severity
{
"affected": [
{
"package": {
"ecosystem": "crates.io",
"name": "block_buffer"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "0.12.1"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [],
"database_specific": {
"cwe_ids": [
"CWE-119"
],
"github_reviewed": true,
"github_reviewed_at": "2026-08-19T19:15:34Z",
"nvd_published_at": null,
"severity": "MODERATE"
},
"details": "### Summary\n\nA caught panic may leave the cursor position of `EagerBuffer` or `ReadBuffer` in a corrupted state; this in turn allows out-of-bounds reads/writes.\n\n### Details \u0026 PoC\n\nThe following two tests fail miri:\n\n```rust\n#[cfg(miri)]\n#[test]\nfn eager_digest_blocks_panic_corrupts_inline_position() {\n // `EagerBuffer` stores its cursor in the last byte of the internal block.\n // When `digest_blocks` completes a previously partial block, it overwrites\n // that byte with input data before invoking the caller-provided `compress`\n // callback. If the callback panics, safe code can catch the panic and keep\n // using the buffer while its cursor byte no longer satisfies the internal\n // `pos \u003c block_size` invariant. Under Miri this `get_pos` call reaches the\n // `unreachable_unchecked` used for the assumed-valid cursor.\n let mut buf = EagerBuffer::\u003cU4\u003e::new(\u0026[1, 2]);\n\n let _ = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {\n buf.digest_blocks(\u0026[3, 0xff], |_| panic!(\"simulated compression failure\"));\n }));\n\n let _ = buf.get_pos();\n}\n\n#[cfg(miri)]\n#[test]\nfn read_buffer_generator_panic_corrupts_inline_position() {\n // `ReadBuffer` stores its cursor in `buffer[0]`, but `write_block` gives\n // `gen_block` mutable access to the whole internal block before restoring\n // `buffer[0]` to a valid cursor. If `gen_block` writes an arbitrary first\n // byte and panics, safe code can catch the panic and later observe an\n // invalid cursor. Under Miri this `get_pos` call reaches the\n // `unreachable_unchecked` used for the assumed-valid cursor.\n let mut buf = ReadBuffer::\u003cU4\u003e::default();\n\n let _ = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {\n buf.write_block(\n 1,\n |block| {\n block[0] = 0xff;\n panic!(\"simulated block generation failure\");\n },\n |_| {},\n );\n }));\n\n let _ = buf.get_pos();\n}\n```\n\nThey fail on an `unreachable_unchecked!()` under the invariant for the `pos` to always be within bounds of the block.\n\n### Impact\n\nWhile the byte that overwrites `pos` may come from untrusted input and is therefore attacker-controlled, this still relies on the surrounding code catching the panic and carrying on, which should be uncommon in practice.\n\nFor this to be exploitable, the attacker also needs a way to trigger a panic here; I have not investigated how feasible that is.\n\n### Credits\n\nThe issue was discovered by GPT-5.5",
"id": "GHSA-qwgh-2vcv-g2f7",
"modified": "2026-08-19T19:15:34Z",
"published": "2026-08-19T19:15:34Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/RustCrypto/utils/security/advisories/GHSA-qwgh-2vcv-g2f7"
},
{
"type": "PACKAGE",
"url": "https://github.com/RustCrypto/utils"
},
{
"type": "WEB",
"url": "https://github.com/RustCrypto/utils/releases/tag/block-buffer-v0.12.1"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N",
"type": "CVSS_V4"
}
],
"summary": "block_buffer: panic corrupts inline buffer position"
}
Loading…
Loading…
Experimental. This forecast is provided for visualization only and may change without notice. Do not use it for operational decisions.
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…
The MITRE ATT&CK techniques below are AI-generated suggestions, inferred from the description of the
vulnerability by the CIRCL/vulnerability-attack-technique-classification-roberta-base
model, served locally by ML-Gateway.
They have not been verified by an analyst and are provided for guidance only.
The approach is described in our paper Mapping CVEs to MITRE ATT&CK Techniques: A Curated Gold-Set Classifier and the Limits of LLM-Assisted Label Expansion.
The approach is described in our paper Mapping CVEs to MITRE ATT&CK Techniques: A Curated Gold-Set Classifier and the Limits of LLM-Assisted Label Expansion.
Loading…
Loading…