RUSTSEC-2026-0431: Unbounded memory allocation in `evtx` parsing a `.wevtcache` file
Affected versions of evtx did not bound a per-entry payload length read from a .wevtcache file before allocating a buffer sized from it, allowing a tiny crafted file to force a multi-gigabyte allocation and abort the process (out-of-memory denial of service, CWE-400).
Details
In WevtCacheReader::nextentry (src/wevttemplates/wevtcache.rs), the per-entry payload length is read as a u64 straight from the file and used to size a zeroing buffer before any data is read:
rust let len = usize::tryfrom(lenu64)?; // u64 taken directly from the entry header let mut buf = vec![0u8; len]; // unbounded allocation, sized from the file reader.readexact(&mut buf)?; // only fails AFTER the allocation
The only check on len is that it fits in usize; there is no check that it fits within the bytes remaining in the file. An entry header declaring a ~4 GiB length therefore makes the crate request a ~4 GiB allocation from a file of only ~25 bytes.
The sink is reachable through the public API evtx::wevttemplates::wevtcache::foreachcrimblob(path, f) (and the WevtCacheReader::nextentry it drives). The .wevtcache reader first shipped in 0.11.0, and every published version from 0.11.0 through 0.14.0 is affected. The code lives in the wevttemplates feature, which is enabled by default through the evtxdump feature. The fix landed in 0.15.1: 0.15.0 was tagged but never published to crates.io (its Windows build failed), so 0.15.1 is the first patched release available. The Python bindings (evtx on PyPI) carry the fix as of 0.15.0.
Reproduction
A ~25-byte file is sufficient: the .wevtcache magic (WEVTCACH), a version (u32 LE) of 1, an entrycount (u32 LE) of 1, then one entry consisting of a kind byte and a len (u64 LE) set to a large value (e.g. 0xFFFFFFF0), with no payload bytes following. Passing that file to foreachcrimblob triggers the oversized allocation before the short read fails.
Affected Software
Event History
Frequently Asked Questions
Which applications are exposed?
Applications that call evtx::wevt_templates::wevtcache::for_each_crim_blob(path, f), or otherwise drive WevtCacheReader::next_entry, on a crafted .wevtcache file are exposed. The vulnerable reader first shipped in evtx 0.11.0.
What does an attacker need to do to trigger the issue?
They need a victim to parse a crafted .wevtcache file. A very small file can declare a multi-gigabyte per-entry payload length, causing allocation before the reader verifies that the declared data exists.
What is the practical impact?
The process can abort due to an out-of-memory condition. The provided severity vector indicates no confidentiality or integrity impact, but high availability impact.
What can be done before a fix is available?
Avoid processing untrusted .wevtcache files through the affected reader. In particular, do not pass attacker-controlled file paths to for_each_crim_blob or other code that reaches WevtCacheReader::next_entry.