# RUSTSEC-2026-0195: Unbounded namespace-declaration allocation in `NsReader` enables memory-exhaustion denial of service

> Remote attackers can cause memory exhaustion and process termination via crafted XML namespace declarations in the quick-xml library.

- **Severity:** Not scored
- **Exploited in the wild:** Not known
- **Login needed:** Not needed
- **Attackable:** Over the internet
- **Victim action needed:** Not needed
- **Fix available:** Yes
- **Published:** 29 Jun 2026

## What is RUSTSEC-2026-0195?

RUSTSEC-2026-0195 is a denial of service vulnerability in quick-xml, published on 29 Jun 2026. An attacker can exploit it over the internet without logging in, with no action from the victim.

### Official description

`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.

## Which versions are affected by RUSTSEC-2026-0195?

1 open source package ship an affected version, including quick-xml.


| Package | Ecosystem | Affected | Fixed in |
| --- | --- | --- | --- |
| `quick-xml` | crates.io | From 0.0.0-0 | 0.41.0 |

## How do I fix RUSTSEC-2026-0195?

Upgrade quick-xml to 0.41.0 or later.

## Is RUSTSEC-2026-0195 being exploited?

There is no known exploitation of RUSTSEC-2026-0195 in the wild and no public exploit code.

## Fix prompt for AI coding agents

```text
Check this codebase for RUSTSEC-2026-0195 and fix it if it is affected.

What it is: RUSTSEC-2026-0195 is a denial of service vulnerability in quick-xml, published on 29 Jun 2026. An attacker can exploit it over the internet without logging in, with no action from the victim.
Exploitation: There is no known exploitation of RUSTSEC-2026-0195 in the wild and no public exploit code.

Affected packages and fixed versions:
- quick-xml (crates.io): affected from 0.0.0-0; fixed in 0.41.0

Task:
1. Search the dependency manifests and lockfiles (for example package.json, package-lock.json, requirements.txt, poetry.lock, uv.lock, pom.xml, build.gradle, go.mod, Cargo.lock, Gemfile.lock) and any Dockerfiles for the affected packages, including transitive dependencies.
2. If an affected version is in use, upgrade it to the fixed version for its release line with the project's package manager, so the lockfile is regenerated. Prefer the smallest upgrade that fixes it.
3. If there is no fix, or the upgrade would break the build, do not guess: explain the risk and the safest workaround instead.
4. Run the tests and summarise what changed and why.
5. If nothing in the project is affected, say so and change nothing.

Reference: https://insights.sbomify.com/RUSTSEC-2026-0195/ (Markdown: https://insights.sbomify.com/RUSTSEC-2026-0195/index.md)
```

## Sources

- OSV: https://osv.dev/vulnerability/RUSTSEC-2026-0195

---
From sbomify Insights: https://insights.sbomify.com/RUSTSEC-2026-0195/
Summaries are generated and may contain mistakes; the official description above is the record.
