rustsec-2026-0431
CVSS 5.5 osv_rustsecAffected 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::next_entry` (`src/wevt_templates/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::try_from(len_u64)?; // u64 taken directly from the entry header let mut buf = vec![0u8; len]; // unbounded allocation, sized from the file reader.read_exact(&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::wevt_templates::wevtcache::for_each_crim_blob(path, f)` (and the `WevtCacheReader::next_entry` 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 `wevt_templates` feature, which is enabled by default through the `evtx_dump` 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 `entry_count` (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 `for_each_crim_blob` triggers the oversized allocation before the short read fails.
- Published
- unknown
- Last Modified
- unknown
CVSS details not available.
No product information available.
No linked vulnerabilities found.
{
"affected": [
{
"database_specific": {
"categories": [
"denial-of-service"
],
"cvss": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H",
"informational": null,
"source": "https://github.com/rustsec/advisory-db/blob/osv/crates/RUSTSEC-2026-0431.json"
},
"ecosystem_specific": {
"affected_functions": null,
"affects": {
"arch": [],
"functions": [
"evtx::wevt_templates::wevtcache::WevtCacheReader::next_entry",
"evtx::wevt_templates::wevtcache::for_each_crim_blob"
],
"os": []
}
},
"package": {
"ecosystem": "crates.io",
"name": "evtx",
"purl": "pkg:cargo/evtx"
},
"ranges": [
{
"events": [
{
"introduced": "0.11.0"
},
{
"fixed": "0.15.1"
}
],
"type": "SEMVER"
}
]
}
],
"database_specific": {
"license": "CC0-1.0"
},
"details": "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).\n\n## Details\n\nIn `WevtCacheReader::next_entry` (`src/wevt_templates/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:\n\n```rust\nlet len = usize::try_from(len_u64)?; // u64 taken directly from the entry header\nlet mut buf = vec![0u8; len]; // unbounded allocation, sized from the file\nreader.read_exact(&mut buf)?; // only fails AFTER the allocation\n```\n\nThe 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.\n\nThe sink is reachable through the public API `evtx::wevt_templates::wevtcache::for_each_crim_blob(path, f)` (and the `WevtCacheReader::next_entry` 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 `wevt_templates` feature, which is enabled by default through the `evtx_dump` 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`.\n\n## Reproduction\n\nA ~25-byte file is sufficient: the `.wevtcache` magic (`WEVTCACH`), a `version` (u32 LE) of `1`, an `entry_count` (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 `for_each_crim_blob` triggers the oversized allocation before the short read fails.",
"id": "RUSTSEC-2026-0431",
"modified": "2026-11-02T11:00:02.238924591Z",
"published": "2026-11-01T12:00:00Z",
"references": [
{
"type": "PACKAGE",
"url": "https://crates.io/crates/evtx"
},
{
"type": "ADVISORY",
"url": "https://rustsec.org/advisories/RUSTSEC-2026-0431.html"
},
{
"type": "REPORT",
"url": "https://github.com/omerbenamram/evtx/issues/334"
},
{
"type": "WEB",
"url": "https://github.com/omerbenamram/evtx/pull/335"
}
],
"schema_version": "1.9.2",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H",
"type": "CVSS_V3"
}
],
"summary": "Unbounded memory allocation in `evtx` parsing a `.wevtcache` file"
}