Expat 2.8.1 released, CVE-2026-45186 and CVSS unreliability
For readers new to Expat:
libexpat is a fast streaming XML parser. Alongside libxml2, Expat is one of the most widely used software libre XML parsers written in C, specifically C99. It is cross-platform and licensed under the MIT license.
Expat 2.8.1 was released yesterday. The key motivation for cutting a release and doing so now was:
- Fixing vulnerability CVE-2026-45186 that allows easy denial of service.
The vulnerability was reported to me responsibly about eight months ago by Nick Wellnhofer, the long-time and past maintainer of libxml2.
The attack relies on Expat <2.8.1 using an
O(n²) runtime algorithm
— a for loop — to check for collisions among attribute names.
It takes nothing more than dialing up XML document…
<!DOCTYPE d [ <!ATTLIST e a0 CDATA "" a1 CDATA "" a2 CDATA ""> ]> <d/>
…from 3 attributes to a number big enough for the specific target of the attack.
It should be noted that a layer of compression around XML can significantly reduce the minimum attack payload size.
There is an attack payload generator available for download: please use it responsibly!
Berkay Eren Ürün and I teamed up
for a fix. It uses a hash table
instead of a linear loop to detect collisions,
which turns overall runtime from O(n*n) into O(n).
For some numbers (from older ThinkPad X220 hardware):
| Count | Runtime unfixed | Runtime fixed | Payload size |
|---|---|---|---|
| (seconds) | (seconds) | (uncompressed, bytes) | |
| 10,000 | 0.17 | 0.03 | 135,615 |
| 100,000 | 13.22 | 0.24 | 1,395,615 |
| 200,000 | 59.71 | 0.49 | 2,795,615 |
| 400,000 | 253.18 | 1.04 | 5,708,119 |
And a quick graph:
It is worth noting that after I filed a CVE request with Mitre,
someone turned my classification as remote (i.e. parsing from the wire)
to mistaken local (i.e. local account access needed) and also to
"Attack complexity: High" when it is a simple as shown above
and with an attack payload generator being public.
That results is a current
CVSS
score "2.9 of 10: LOW" on GitHub…
…and also in NVD. I have requested a fix from Mitre in the mean time, but that's not fixing the core issue. This could serve as both a concrete example and a reminder that:
-
CVSS scores are unreliable: they are often over- or (worse) underestimating risk.
-
CVSS scores (and CVE reports) are edited by individuals that may or may not know better than the reporting individuals and/or the maintainers upstream.
-
CVSS score is not a metric to base decisions about vulnerabilities on.
Thanks to everyone who contributed to this release of Expat!
For more details about this release, please check out the change log.
If you maintain Expat packaging, a bundled copy of Expat, or a pinned version of Expat, please update to version 2.8.1. Thank you!
Sebastian Pipping