rustsec-2026-0403
debian_rustsecWhen decompression fails inside a legacy (zstd v0.4 to v0.7) frame, the bundled zstd library reports the output buffer as fully written although nothing was written. `DCtx::decompress_stream` committed that position even on error, and for a `Vec<u8>` destination this extended the vector's length over uninitialized memory. Legacy support is enabled by default. A 5- or 6-byte corrupt legacy frame is enough: through `zstd::stream::write::Decoder`, up to 32 KiB of stale heap memory is then passed to the wrapped writer on the next `write()` or `flush()`, or when an `auto_flush()`/`on_flush()` decoder is dropped. Whether this reaches an attacker depends on where the application sends the decompressed output. `zstd::stream::read::Decoder`, `zstd::decode_all` and the bulk API are not affected. Before zstd-safe 4.0.0, output buffers could only be initialized slices. The zstd crate's own writer had the same flaw from 0.4.22 to 0.7.x, which is covered by a separate advisory. The flaw was corrected by only committing the buffer positions of a successful call.
- Published
- unknown
- Last Modified
- unknown
CVSS details not available.
No product information available.
No references available.
No linked vulnerabilities found.
{
"aliases": [],
"categories": [
"memory-exposure"
],
"crate": "zstd-safe",
"cves": [],
"cvss": 0.0,
"database_specific": {
"severity": ""
},
"date": "2026-10-16",
"deb_packages": [
{
"crate_name": "debian-repro-status",
"deb_name": "debian-repro-status",
"version": "0.4.0-3"
},
{
"crate_name": "doxx",
"deb_name": "doxx",
"version": "0.1.4+ds-1"
},
{
"crate_name": "git-cinnabar",
"deb_name": "git-cinnabar",
"version": "0.7.3-2+b2"
},
{
"crate_name": "zstd-safe",
"deb_name": "librust-zstd-safe-dev",
"version": "7.2.4-1+b1"
},
{
"crate_name": "miniserve",
"deb_name": "miniserve",
"version": "0.35.0-6"
},
{
"crate_name": "protonup-rs",
"deb_name": "protonup-rs",
"version": "0.15.0-1+b2"
},
{
"crate_name": "rebuildctl",
"deb_name": "rebuildctl",
"version": "0.28.0-2"
},
{
"crate_name": "rebuilderd",
"deb_name": "rebuilderd",
"version": "0.28.0+ds-2+b2"
},
{
"crate_name": "rebuilderd-worker",
"deb_name": "rebuilderd-worker",
"version": "0.28.0-1+b2"
},
{
"crate_name": null,
"deb_name": "rustup",
"version": "1.27.1-8+b2"
},
{
"crate_name": "samply",
"deb_name": "samply",
"version": "0.13.1-1+b2"
},
{
"crate_name": null,
"deb_name": "ty",
"version": "0.0.85+ruff0.16.10+ds-2"
}
],
"description": "When decompression fails inside a legacy (zstd v0.4 to v0.7) frame, the\nbundled zstd library reports the output buffer as fully written although\nnothing was written. `DCtx::decompress_stream` committed that position even\non error, and for a `Vec<u8>` destination this extended the vector's length\nover uninitialized memory.\n\nLegacy support is enabled by default. A 5- or 6-byte corrupt legacy frame is\nenough: through `zstd::stream::write::Decoder`, up to 32 KiB of stale heap\nmemory is then passed to the wrapped writer on the next `write()` or\n`flush()`, or when an `auto_flush()`/`on_flush()` decoder is dropped. Whether\nthis reaches an attacker depends on where the application sends the\ndecompressed output. `zstd::stream::read::Decoder`, `zstd::decode_all` and\nthe bulk API are not affected.\n\nBefore zstd-safe 4.0.0, output buffers could only be initialized slices.\nThe zstd crate's own writer had the same flaw from 0.4.22 to 0.7.x, which is\ncovered by a separate advisory.\n\nThe flaw was corrected by only committing the buffer positions of a\nsuccessful call.",
"id": "RUSTSEC-2026-0403",
"keywords": [
"uninitialized-memory",
"decompression",
"legacy"
],
"patched_versions": [
"^7.4.0",
">=8.2.0"
],
"source": "debian_rustsec",
"title": "Uninitialized memory exposed when streaming decompression of a legacy frame fails",
"url": "https://github.com/gyscos/zstd-rs/commit/006e1d1ad1eeaf6b5d4c28329e70217adabcec43"
}