RUSTSEC-2026-0403
Uninitialized memory exposed when streaming decompression of a legacy frame fails
- Severity
- Not rated yet
- No source has published a CVSS score yet
- Exploit chance (EPSS)
- —
- No score published
- Known exploited
- No
- Not in CISA's catalog
- Weakness
- —
- Not classified
- Fix
8.2.0- Upgrade zstd-safe to this version or later
Description
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.
Affected versions
crates.io
| Package | Vulnerable | Fixed in |
|---|---|---|
| zstd-safe | >= 4.0.0, < 8.2.0 |
8.2.0 |
How to fix
Move to the fixed version or later with your package manager, update the lockfile, and run your tests. If the package only arrives through another dependency, upgrade that dependency first. If none of its releases pulls a fixed version yet, force the version with your package manager's override.
zstd-safe crates.io → 8.2.0
- cargo
cargo update -p zstd-safe --precise 8.2.0
References
Advisories
Packages
Other links
Timeline
- Published
- Last updated by the source
Related advisories
| Advisory | Severity | Why it's related |
|---|---|---|
| RUSTSEC-2026-0406 Use-after-free when changing a multithreaded context with an unfinished frame | Not rated yet | Also affects zstd-safe |
| RUSTSEC-2026-0405 Out-of-bounds read with an out-of-range `InBuffer::pos` | Not rated yet | Also affects zstd-safe |
| RUSTSEC-2026-0404 Double free in `DCtx::try_clone` | Not rated yet | Also affects zstd-safe |
| RUSTSEC-2026-0402 Heap buffer overflow in `CCtx::try_clone` on a multithreaded context | Not rated yet | Also affects zstd-safe |
| RUSTSEC-2026-0401 Out-of-bounds read in `train_from_buffer` when sample sizes overflow | Not rated yet | Also affects zstd-safe |
| RUSTSEC-2026-0400 Use-after-free of a dictionary after a one-shot call on a context with an open stream | Not rated yet | Also affects zstd-safe |
| RUSTSEC-2026-0399 Use-after-free through `init_using_cdict` and `init_using_ddict` | Not rated yet | Also affects zstd-safe |
| RUSTSEC-2026-0398 `Seekable::decompress` sets a `Vec` length beyond its capacity for offsets past the end | Not rated yet | Also affects zstd-safe |
MergeHarbor checks every repository's dependencies against this database, ranks what matters by exploitability and reachability, routes it to the owning team and opens the fix pull request.
Check your repos with MergeHarbor