RUSTSEC-2026-0403None▾ SunlitUninitialized memory exposed when streaming decompression of a legacy frame fails
▾ Sunlit zone — Low / medium · no exploitation signal
impact 2.8 · likelihood 0 · exploitation 0
Need a working PoC? Pro members can cast a request and our team develops one — it lands right here.
Disclosure to exploitation, from the record and what we observed since indexing it.
Disclosed via OSV
Last analysed / modified upstream
When 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.
zstd-safe >= 8.0.0-0, < 8.2.0Upgrade to a patched release:
zstd-safe 8.2.0Connected by shared product, vendor, weakness, or advisory.
RUSTSEC-2026-0406NoneUse-after-free when changing a multithreaded context with an unfinished frame
RUSTSEC-2026-0405NoneOut-of-bounds read with an out-of-range `InBuffer::pos`
RUSTSEC-2026-0404NoneDouble free in `DCtx::try_clone`
RUSTSEC-2026-0402NoneHeap buffer overflow in `CCtx::try_clone` on a multithreaded context
RUSTSEC-2026-0401NoneOut-of-bounds read in `train_from_buffer` when sample sizes overflow
RUSTSEC-2026-0399NoneUse-after-free through `init_using_cdict` and `init_using_ddict`