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:
parent
64275925e4
commit
77482ccb26
118
assertj-core-3.19.0-CVE-2026-24400.patch
Normal file
118
assertj-core-3.19.0-CVE-2026-24400.patch
Normal 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
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user