Skip to content

RUSTSEC-2026-0403

Uninitialized memory exposed when streaming decompression of a legacy frame fails

Not rated yet crates.io
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

PackageVulnerableFixed 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

Timeline

  1. Published
  2. Last updated by the source
AdvisorySeverityWhy 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
Is this in your code?

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