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
This commit is contained in:
RHEL Packaging Agent 2026-06-25 12:38:16 +00:00 committed by Marian Koncek
parent 64275925e4
commit 77482ccb26
2 changed files with 127 additions and 1 deletions

View File

@ -0,0 +1,118 @@
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

View File

@ -2,12 +2,15 @@
Name: assertj-core
Version: 3.19.0
Release: 9%{?dist}
Release: 10%{?dist}
Summary: Library of assertions similar to fest-assert
License: ASL 2.0
URL: https://joel-costigliola.github.io/assertj/
Source0: https://github.com/joel-costigliola/assertj-core/archive/assertj-core-%{version}.tar.gz
# https://github.com/assertj/assertj/commit/77081dc5eb107141df80f95bd0149b468e451341
Patch0: assertj-core-3.19.0-CVE-2026-24400.patch
BuildArch: noarch
ExclusiveArch: aarch64 ppc64le s390x x86_64 noarch
@ -34,6 +37,7 @@ This package provides API documentation for %{name}.
%prep
%setup -q -n assertj-core-assertj-core-%{version}
%patch -P0 -p1
%pom_remove_parent
%pom_xpath_inject "pom:project" "<groupId>org.assertj</groupId>"
@ -72,6 +76,10 @@ rm -r src/test/java/org/assertj/core/internal/{Paths*.java,paths}
%license LICENSE.txt
%changelog
* Thu Jun 25 2026 RHEL Packaging Agent <redhat-ymir-agent@redhat.com> - 3.19.0-10
- Fix CVE-2026-24400: prevent XXE attacks in XmlStringPrettyFormatter
- Resolves: RHEL-208834
* Sun Nov 24 2024 Marián Konček <mkoncek@redhat.com> - 3.19.0-9
- Do not install CONTRIBUTING.md in javadoc package