assertj-core/assertj-core-3.19.0-CVE-2026-24400.patch
RHEL Packaging Agent 77482ccb26 Fix CVE-2026-24400: XXE vulnerability in assertj-core
Backport upstream commit 77081dc5e to assertj-core 3.19.0 to
fix CVE-2026-24400. The patch hardens XmlStringPrettyFormatter
against XML External Entity (XXE) attacks by enabling
FEATURE_SECURE_PROCESSING and disallowing DOCTYPE declarations
in the XML parser configuration. Two new tests verify that
inputs containing DOCTYPE declarations with entity and
parameter entity injections are properly rejected.

CVE: CVE-2026-24400
Upstream patches:
 - 77081dc5eb.patch

Resolves: RHEL-208834

This commit was backported by Ymir, a Red Hat Enterprise Linux software maintenance AI agent.

Assisted-by: Ymir
2026-07-17 14:57:48 +02:00

119 lines
5.1 KiB
Diff

From 207217290a4de35386444c32c5c52cf97c4e9b5e Mon Sep 17 00:00:00 2001
From: Stefano Cordio <stefano.cordio@gmail.com>
Date: Sat, 24 Jan 2026 19:47:47 +0100
Subject: [PATCH] Merge commit from fork
---
.../util/xml/XmlStringPrettyFormatter.java | 27 +++++++++++++-
...ringPrettyFormatter_prettyFormat_Test.java | 35 +++++++++++++++++++
2 files changed, 61 insertions(+), 1 deletion(-)
diff --git a/src/main/java/org/assertj/core/util/xml/XmlStringPrettyFormatter.java b/src/main/java/org/assertj/core/util/xml/XmlStringPrettyFormatter.java
index 0956ddf8b..bbec9106e 100644
--- a/src/main/java/org/assertj/core/util/xml/XmlStringPrettyFormatter.java
+++ b/src/main/java/org/assertj/core/util/xml/XmlStringPrettyFormatter.java
@@ -17,9 +17,13 @@ import static org.assertj.core.util.Preconditions.checkArgument;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
+import java.util.HashMap;
+import java.util.Map;
+import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.bootstrap.DOMImplementationRegistry;
@@ -39,6 +43,17 @@ public class XmlStringPrettyFormatter {
private static final String FORMAT_ERROR = "Unable to format XML string";
+ // https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html
+ private static final Map<String, Boolean> SECURE_FEATURES = new HashMap<>();
+
+ static {
+ SECURE_FEATURES.put(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+ SECURE_FEATURES.put("http://apache.org/xml/features/disallow-doctype-decl", true);
+ SECURE_FEATURES.put("http://xml.org/sax/features/external-general-entities", false);
+ SECURE_FEATURES.put("http://xml.org/sax/features/external-parameter-entities", false);
+ SECURE_FEATURES.put("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
+ }
+
public static String xmlPrettyFormat(String xmlStringToFormat) {
checkArgument(xmlStringToFormat != null, "Expecting XML String not to be null");
// convert String to an XML Document and then back to String but prettily formatted.
@@ -67,13 +82,23 @@ public class XmlStringPrettyFormatter {
private static Document toXmlDocument(String xmlString) {
try {
InputSource xmlInputSource = new InputSource(new StringReader(xmlString));
- DocumentBuilder xmlDocumentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ DocumentBuilder xmlDocumentBuilder = documentBuilderFactory().newDocumentBuilder();
return xmlDocumentBuilder.parse(xmlInputSource);
} catch (Exception e) {
throw new RuntimeException(FORMAT_ERROR, e);
}
}
+ private static DocumentBuilderFactory documentBuilderFactory() {
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ SECURE_FEATURES.forEach((name, value) -> {
+ try {
+ factory.setFeature(name, value);
+ } catch (ParserConfigurationException ignore) {}
+ });
+ return factory;
+ }
+
private XmlStringPrettyFormatter() {
// utility class
}
diff --git a/src/test/java/org/assertj/core/util/xml/XmlStringPrettyFormatter_prettyFormat_Test.java b/src/test/java/org/assertj/core/util/xml/XmlStringPrettyFormatter_prettyFormat_Test.java
index c2c3e574d..21f00df42 100644
--- a/src/test/java/org/assertj/core/util/xml/XmlStringPrettyFormatter_prettyFormat_Test.java
+++ b/src/test/java/org/assertj/core/util/xml/XmlStringPrettyFormatter_prettyFormat_Test.java
@@ -97,4 +97,39 @@ class XmlStringPrettyFormatter_prettyFormat_Test {
}
}
+ @Test
+ void should_fail_if_input_contains_doctype_declaration_with_entity() {
+ // Injection into document content
+ String xmlString = "<?xml version=\"1.0\"?>\n"
+ + "<!DOCTYPE root [\n"
+ + " <!ENTITY xxe SYSTEM \"file:///etc/hosts\">\n"
+ + "]>\n"
+ + "<root>&xxe;</root>";
+ try {
+ xmlPrettyFormat(xmlString);
+ } catch (Exception e) {
+ assertThat(e).isInstanceOf(RuntimeException.class).hasMessage("Unable to format XML string");
+ assertThat(e.getCause()).isInstanceOf(SAXParseException.class)
+ .hasMessageContaining("DOCTYPE is disallowed");
+ }
+ }
+
+ @Test
+ void should_fail_if_input_contains_doctype_declaration_with_parameter_entity() {
+ // Injection during document parsing
+ String xmlString = "<?xml version=\"1.0\"?>\n"
+ + "<!DOCTYPE root [\n"
+ + " <!ENTITY % xxe SYSTEM \"file:///etc/hosts\">\n"
+ + " %xxe;\n"
+ + "]>\n"
+ + "<root>foo</root>";
+ try {
+ xmlPrettyFormat(xmlString);
+ } catch (Exception e) {
+ assertThat(e).isInstanceOf(RuntimeException.class).hasMessage("Unable to format XML string");
+ assertThat(e.getCause()).isInstanceOf(SAXParseException.class)
+ .hasMessageContaining("DOCTYPE is disallowed");
+ }
+ }
+
}
--
2.52.0