Vulnerability HighRUSTSEC-2026-0195 · quick-xml
RUSTSEC-2026-0195: Unbounded namespace-declaration allocation in `NsReader` enables memory-exhaustion denial of service
Short answerA security vulnerability in the quick-xml crate: Unbounded namespace-declaration allocation in `NsReader` enables memory-exhaustion denial of service. High severity (CVSS 7.5). Fixed in 0.41.0: update to a fixed version.
| Crate | quick-xml |
|---|---|
| Type | Vulnerability (denial-of-service) |
| Affected versions | Before 0.41.0. |
| Fixed in | 0.41.0 |
| Severity | High, CVSS 7.5 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H |
| Published | 2026-06-29 |
| Last changed | 2026-07-02 |
| Also known as | none |
What to do
- See which version you have:
cargo tree -i quick-xml(it also shows which of your dependencies pulls it in). - Update within your version requirement:
cargo update -p quick-xml. If the fix is a newer major or minor than your requirement allows, raise it in Cargo.toml (for examplequick-xml = "0.41.0") or update the dependency that pulls it in. - Check again with
cargo audit, or paste your Cargo.lock into our Cargo.toml checker.
Details from the advisory
NsReader resolves namespaces by calling NamespaceResolver::push for every Start/Empty event *before* the event is returned to the caller. push iterated all xmlns / xmlns:* attributes on the start tag and, for each one, appended the prefix bytes to an internal buffer and pushed a NamespaceBinding (32 bytes on 64-bit) to an internal Vec, with no upper bound on the number of declarations.
Impact
A start tag with N namespace declarations drove roughly 3× the tag's byte size in NamespaceResolver heap, allocated *inside* quick-xml before the NsReader consumer ever received the event and could inspect or reject it. A consumer that bounds its *input* size therefore still cannot bound this allocation: an M-byte start tag yields on the order of 3 × M bytes of resolver heap the caller never sees.
On untrusted XML this lets a remote, unauthenticated attacker force large heap allocations with a single start tag. With several NsReaders running concurrently on independent inputs (a common server pattern), the allocations stack and can exhaust process memory, causing the operating system to kill the process (OOM). This was confirmed against a real-world RPKI relying party (NLnet Labs Routinator), where concurrent RRDP validation workers parsing a crafted snapshot.xml exceeded the memory limit and the process was OOM-killed.
Affected code paths
Consumers using NsReader (which always calls NamespaceResolver::push before yielding Start/Empty), or calling NamespaceResolver::push directly. A plain Reader that does not perform namespace resolution is not affected.
Remediation
Upgrade to quick-xml >= 0.41.0. NamespaceResolver::push now rejects a start tag that declares more than DEFAULT_MAX_DECLARATIONS_PER_ELEMENT (256) namespace bindings, returning the new NamespaceError::TooManyDeclarations instead of allocating without limit. The limit is configurable via NamespaceResolver::set_max_declarations_per_element (use usize::MAX to restore the previous unbounded behavior), and NsReader::resolver_mut() is provided to reach it.
There is no clean workaround for NsReader consumers before 0.41.0, as the allocation happens inside the reader with no configuration knob to cap it.
References
- Package: crates.io/crates/quick-xml
- Advisory: rustsec.org/advisories/RUSTSEC-2026-0195.html
- Report: github.com/tafia/quick-xml/issues/970
- Web: github.com/tafia/quick-xml/commit/7ca25266e94987210daa864889ab15c9332c8a2a
From the RustSec Advisory Database (CC0-1.0) via the OSV export, downloaded Oct 24, 2026. Severity score computed from the published CVSS vector.
Other advisories for quick-xml
Up next
Same cratequick-xml: security historyEvery advisory for this crate, and whether it is safe to use today.Read it next →Did this answer your question?