CVE-2025-58058 is a medium-severity (CVSS 5.3) CWE-770 vulnerability in github.com/ulikunitz/xz. A fix is available for github.com/ulikunitz/xz — see the affected versions and patch details below.
github.com/ulikunitz/xz leaks memory when decoding a corrupted multiple LZMA archives
EPSS Exploitation Probability
Probability of exploitation in the next 30 days, from FIRST.org EPSS.
How urgent is this, really
Where this sits among everything scored
Real-World Exposure
github.com/ulikunitz/xzReal-time download stats are indexed for npm and PyPI packages. This vulnerability affects Go packages — download data is not available via public APIs for these ecosystems.
Description
Summary
It is possible to put data in front of an LZMA-encoded byte stream without detecting the situation while reading the header. This can lead to increased memory consumption because the current implementation allocates the full decoding buffer directly after reading the header. The LZMA header doesn't include a magic number or has a checksum to detect such an issue according to the specification.
Note that the code recognizes the issue later while reading the stream, but at this time the memory allocation has already been done.
Mitigations
The release v0.5.15 includes following mitigations:
- The ReaderConfig DictCap field is now interpreted as a limit for the dictionary size.
- The default is 2 Gigabytes - 1 byte (2^31-1 bytes).
- Users can check with the [Reader.Header] method what the actual values are in their LZMA files and set a smaller limit using ReaderConfig.
- The dictionary size will not exceed the larger of the file size and the minimum dictionary size. This is another measure to prevent huge memory allocations for the dictionary.
- The code supports stream sizes only up to a pebibyte (1024^5).
Note that the original v0.5.14 version had a compiler error for 32 bit platforms, which has been fixed by v0.5.15.
Methods affected
Only software that uses lzma.NewReader or lzma.ReaderConfig.NewReader is affected. There is no issue for software using the xz functionality.
I thank @GregoryBuligin for his report, which is provided below.
Summary
When unpacking a large number of LZMA archives, even in a single goroutine, if the first byte of the archive file is 0 (a zero byte added to the beginning), an error writeMatch: distance out of range occurs. Memory consumption spikes sharply, and the GC clearly cannot handle this situation.
Details
Judging by the error writeMatch: distance out of range, the problems occur in the code around this function. https://github.com/ulikunitz/xz/blob/c8314b8f21e9c5e25b52da07544cac14db277e89/lzma/decoderdict.go#L81
PoC
Run a function similar to this one in 1 or several goroutines on a multitude of LZMA archives that have a 0 (a zero byte) added to the beginning.
const ProjectLocalPath = "some/path"
const TmpDir = "tmp"
func UnpackLZMA(lzmaFile string) error {
file, err := os.Open(lzmaFile)
if err != nil {
return err
}
defer file.Close()
reader, err := lzma.NewReader(bufio.NewReader(file))
if err != nil {
return err
}
tmpFile, err := os.CreateTemp(TmpDir, TmpLZMAPrefix)
if err != nil {
return err
}
defer func() {
tmpFile.Close()
_ = os.Remove(tmpFile.Name())
}()
sha256Hasher := sha256.New()
multiWriter := io.MultiWriter(tmpFile, sha256Hasher)
if _, err = io.Copy(multiWriter, reader); err != nil {
return err
}
unpackHash := hex.EncodeToString(sha256Hasher.Sum(nil))
unpackDir := filepath.Join(
ProjectLocalPath, unpackHash[:2],
)
_ = os.MkdirAll(unpackDir, DirPerm)
unpackPath := filepath.Join(unpackDir, unpackHash)
return os.Rename(tmpFile.Name(), unpackPath)
}
Impact
Servers with a small amount of RAM that download and unpack a large number of unverified LZMA archives
Affected Packages
| Ecosystem | Package | Vulnerable range | Fix |
|---|---|---|---|
| 🐹Go | github.com/ulikunitz/xz | all versions | 0.5.15go get github.com/ulikunitz/xz@v0.5.15 |
Detection & mitigation playbook
Open-source dependencyDetect
Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for github.com/ulikunitz/xz, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.
Fix
Update github.com/ulikunitz/xz to 0.5.15 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2025-58058 is resolved across your whole dependency graph.
Workarounds
Cap what an attacker can consume: apply request size, rate and timeout limits in front of the affected component, and run it with memory and CPU limits so exhaustion degrades one worker rather than the whole service.
Fixing This On Your OS
If you run this on a Linux distribution, patch through your package manager against the distro's own security advisory below — it tracks the exact backported fix for your release, which can ship on a different timeline (and sometimes a different severity) than the upstream project.
Mitigation for this issue is either not available or the currently available options do not meet the Red Hat Product Security criteria comprising ease of use and deployment, applicability to widespread installation base or stability.Source: Red Hat security advisory for CVE-2025-58058 (CC BY 4.0)
| Product | Fixed in | Advisory |
|---|---|---|
| multicluster engine for Kubernetes 2.8 | multicluster-engine/assisted-service-8-rhel8:1781539691 | RHSA-2026:26257 |
| multicluster engine for Kubernetes 2.8 | multicluster-engine/assisted-service-9-rhel9:1781539725 | RHSA-2026:26254 |
| Red Hat Openshift Data Foundation 4.22 | odf4/cephcsi-rhel9:1782932114 | RHSA-2026:37387 |
Frequently Asked Questions
Is CVE-2025-58058 in your dependencies?
Find it across Go, including transitive dependencies.