tauri-apps / tauri-apps/plugins-workspace
RUSTSEC-2026-0195: Unbounded namespace-declaration allocation in `NsReader` enables memory-exhaustion denial of service
- Dominant language
- Rust
- Stars
- 1.8k
- Forks
- 602
- Avg merge
- 4d 14h
- Merged PRs (30d)
- 9
Description
> Unbounded namespace-declaration allocation in `NsReader` enables memory-exhaustion denial of service
| Details | |
| ------------------- | ---------------------------------------------- |
| Package | `quick-xml` |
| Version | `0.37.4` |
| URL | [https://github.com/tafia/quick-xml/issues/970](https://github.com/tafia/quick-xml/issues/970) |
| Date | 2026-06-29 |
| Patched versions | `>=0.41.0` |
`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 `NsReader`s 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.
See [advisory page](https://rustsec.org/advisories/RUSTSEC-2026-0195.html) for additional details.
Contributor guide
Research direction
The payload names no repository file, test, or entry point. Start by locating the dependency declaration for quick-xml and checking whether this workspace uses an affected version; then run the relevant project checks. Done means the workspace no longer relies on quick-xml 0.37.4 or another version below 0.41.0.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- security
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100