Debian Rust Security Tracker 🩺🦀

RUSTSEC-2026-0194: Quadratic run time when checking a start tag for duplicate attribute names

high 16 affected
Crate
quick-xml
Patched Versions
>=0.41.0
Debian Version
0.38.4-1+b1
Debian Bugs
#1141595
Issued
2026-06-29
Aliases
Patched:Affected

BytesStart::attributes() returns an Attributes iterator which, by default (with_checks(true)), rejects a start tag that repeats an attribute name. For each attribute yielded, the iterator compared the new name against every name seen so far in the same tag using a linear scan, so a start tag with N distinct attribute names cost O(N²) byte comparisons. There was no bound on N other than the size of the buffered start tag.

Impact

Any code that parses untrusted XML and iterates a start tag's attributes with the default duplicate check enabled can be made to spend CPU time quadratic in the number of attributes on a single tag. Because the check is pure computation with no .await/I/O, an I/O-based timeout on the consumer (for example a read or request timeout) cannot interrupt it while it runs.

Measured cost of a single start tag, release build:

| Attributes on one tag | Time | |---|---| | 80,000 | ~6 s | | 800,000 | ~10 min |

The cost grows with the square of the attribute count, so a start tag of a few tens of megabytes can stall a parsing thread for hours. No memory is exhausted and the parser does not crash; the effect is CPU exhaustion on the thread doing the parsing: a single crafted start tag can pin a CPU core for minutes to hours, denying service to that worker. A deployment that places a wall-clock bound on parsing, or confines it to a non-critical thread, may consider the availability impact lower.

Affected code paths

  • BytesStart::attributes() / Attributes iterated with checks enabled (the default), and BytesStart::try_get_attribute.
  • NsReader, which resolves namespaces by iterating a tag's attributes and so reaches the same check internally.

Consumers that iterate attributes with .attributes().with_checks(false) and do not use NsReader are not affected.

This was reported as reachable by a remote, unauthenticated attacker in a real-world RPKI relying party (NLnet Labs Routinator) via a crafted RRDP snapshot.xml.

Remediation

Upgrade to quick-xml >= 0.41.0, where the duplicate check keeps the linear scan for start tags with a small number of attributes and switches to an O(1) hash pre-filter above a threshold, making the whole tag O(N). The reported AttrError::Duplicated positions are unchanged.

If upgrading is not possible and duplicate-name detection is not required, disable it with .attributes().with_checks(false) (this does not help NsReader consumers, which have no equivalent opt-out before 0.41.0).

Affected Packages

quick-xml 0.38.4 bat 0.26.1+dfsg-2+b1
quick-xml 0.38.4 bmap-rs 0.2.2-1
quick-xml 0.38.4 broot 1.57.0+dfsg-3+b1
quick-xml 0.38.4 czkawka-cli 11.0.1-1+b3
quick-xml 0.38.4 czkawka-gui 11.0.1-3+b1
quick-xml 0.38.4 doxx 0.1.4+dfsg-1+b1
quick-xml 0.38.4 eza 0.23.5-1
quick-xml 0.38.4 feluda 1.15.0-1
quick-xml 0.38.4 grcov 0.10.7-1+b1
quick-xml 0.38.4 inquest 0.3.2-1
affected ⚠️ librust-quick-xml-dev 0.38.4-1+b1
quick-xml 0.38.4 numbat 1.11.0-5+b1
quick-xml 0.38.4 presenterm 0.16.1+dfsg-2
quick-xml 0.38.4 rockusb 0.2.0-3+b1
quick-xml 0.38.4 xh 0.26.2-1
quick-xml 0.38.4 xleak 0.2.6+dfsg-1+b1