You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by jb...@apache.org on 2022/11/15 16:06:12 UTC

[activemq-artemis] branch main updated: ARTEMIS-4077 Add an option to disable XML external entity processing

This is an automated email from the ASF dual-hosted git repository.

jbertram pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/activemq-artemis.git


The following commit(s) were added to refs/heads/main by this push:
     new 3a13a7850c ARTEMIS-4077 Add an option to disable XML external entity processing
3a13a7850c is described below

commit 3a13a7850cf2cd73a3ad276ac4c05f9b04580646
Author: Domenico Francesco Bruscino <br...@apache.org>
AuthorDate: Wed Oct 26 19:26:03 2022 +0200

    ARTEMIS-4077 Add an option to disable XML external entity processing
---
 .../cli/commands/tools/xml/XmlDataImporter.java    |  14 +-
 .../factory/serialize/XMLMessageSerializer.java    |   4 +-
 .../org/apache/activemq/cli/test/ArtemisTest.java  |   9 +-
 .../apache/activemq/artemis/utils/XmlProvider.java | 265 +++++++++++++++++++++
 .../activemq/artemis/utils/XmlProviderTest.java    | 134 +++++++++++
 .../resources/document-with-xinclude-title.xml     |  17 ++
 .../src/test/resources/document-with-xinclude.xml  |  19 ++
 artemis-commons/src/test/resources/document.xml    |  19 ++
 .../src/test/resources/schema-with-import.xsd      |  20 ++
 artemis-commons/src/test/resources/schema.xsd      |  26 ++
 .../org/apache/activemq/artemis/utils/XMLUtil.java |  20 +-
 .../org/apache/activemq/artemis/dto/XmlUtil.java   |  15 +-
 .../artemis/selector/filter/XPathExpression.java   |  29 ++-
 .../deployers/impl/FileConfigurationParser.java    |   8 +-
 .../core/config/impl/FileConfigurationTest.java    |  15 ++
 .../config/impl/FileXIncludeConfigurationTest.java |   6 +
 docs/user-manual/en/configuration-index.md         |   5 +
 .../tests/integration/amqp/XmlExportTest.java      |   4 +-
 .../unit/ra/ActiveMQResourceAdapterConfigTest.java |   5 +-
 19 files changed, 569 insertions(+), 65 deletions(-)

diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/xml/XmlDataImporter.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/xml/XmlDataImporter.java
index 545cdd7968..e563907932 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/xml/XmlDataImporter.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/xml/XmlDataImporter.java
@@ -16,13 +16,9 @@
  */
 package org.apache.activemq.artemis.cli.commands.tools.xml;
 
-import javax.xml.XMLConstants;
-import javax.xml.stream.XMLInputFactory;
 import javax.xml.stream.XMLStreamConstants;
 import javax.xml.stream.XMLStreamReader;
 import javax.xml.transform.stax.StAXSource;
-import javax.xml.validation.Schema;
-import javax.xml.validation.SchemaFactory;
 import javax.xml.validation.Validator;
 import java.io.File;
 import java.io.FileInputStream;
@@ -63,6 +59,7 @@ import org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants;
 import org.apache.activemq.artemis.core.server.ActiveMQServerLogger;
 import org.apache.activemq.artemis.utils.ClassloadingUtil;
 import org.apache.activemq.artemis.utils.ListUtil;
+import org.apache.activemq.artemis.utils.XmlProvider;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import java.lang.invoke.MethodHandles;
@@ -175,7 +172,7 @@ public final class XmlDataImporter extends ActionAbstract {
    public void process(InputStream inputStream,
                        ClientSession session,
                        ClientSession managementSession) throws Exception {
-      reader = XMLInputFactory.newInstance().createXMLStreamReader(inputStream);
+      reader = XmlProvider.createXMLStreamReader(inputStream);
       messageReader = new XMLMessageImporter(reader, session);
       messageReader.setOldPrefixTranslation(oldPrefixTranslation);
 
@@ -219,11 +216,8 @@ public final class XmlDataImporter extends ActionAbstract {
    }
 
    public void validate(InputStream inputStream) throws Exception {
-      XMLStreamReader reader = XMLInputFactory.newInstance().createXMLStreamReader(inputStream);
-      SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
-      Schema schema = factory.newSchema(XmlDataImporter.findResource("schema/artemis-import-export.xsd"));
-
-      Validator validator = schema.newValidator();
+      XMLStreamReader reader = XmlProvider.createXMLStreamReader(inputStream);
+      Validator validator = XmlProvider.newValidator(XmlDataImporter.findResource("schema/artemis-import-export.xsd"));
       validator.validate(new StAXSource(reader));
       reader.close();
    }
diff --git a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/factory/serialize/XMLMessageSerializer.java b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/factory/serialize/XMLMessageSerializer.java
index e353b94240..06623787c0 100644
--- a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/factory/serialize/XMLMessageSerializer.java
+++ b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/factory/serialize/XMLMessageSerializer.java
@@ -18,7 +18,6 @@ package org.apache.activemq.artemis.cli.factory.serialize;
 
 import javax.jms.Message;
 import javax.jms.Session;
-import javax.xml.stream.XMLInputFactory;
 import javax.xml.stream.XMLOutputFactory;
 import javax.xml.stream.XMLStreamReader;
 import javax.xml.stream.XMLStreamWriter;
@@ -36,6 +35,7 @@ import org.apache.activemq.artemis.cli.commands.tools.xml.XmlDataConstants;
 import org.apache.activemq.artemis.cli.commands.tools.xml.XmlDataExporter;
 import org.apache.activemq.artemis.jms.client.ActiveMQMessage;
 import org.apache.activemq.artemis.jms.client.ActiveMQSession;
+import org.apache.activemq.artemis.utils.XmlProvider;
 
 public class XMLMessageSerializer implements MessageSerializer {
 
@@ -87,7 +87,7 @@ public class XMLMessageSerializer implements MessageSerializer {
 
    @Override
    public void setInput(InputStream inputStream, Session session) throws Exception {
-      XMLStreamReader streamReader = XMLInputFactory.newInstance().createXMLStreamReader(inputStream);
+      XMLStreamReader streamReader = XmlProvider.createXMLStreamReader(inputStream);
       this.clientSession = ((ActiveMQSession) session).getCoreSession();
       this.reader = new XMLMessageImporter(streamReader, clientSession);
    }
diff --git a/artemis-cli/src/test/java/org/apache/activemq/cli/test/ArtemisTest.java b/artemis-cli/src/test/java/org/apache/activemq/cli/test/ArtemisTest.java
index 3d09920b72..fab3eb1110 100644
--- a/artemis-cli/src/test/java/org/apache/activemq/cli/test/ArtemisTest.java
+++ b/artemis-cli/src/test/java/org/apache/activemq/cli/test/ArtemisTest.java
@@ -29,10 +29,8 @@ import org.apache.activemq.artemis.api.core.QueueConfiguration;
 import org.apache.activemq.artemis.json.JsonArray;
 import org.apache.activemq.artemis.json.JsonObject;
 import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.stream.StreamResult;
 import java.io.BufferedReader;
@@ -94,6 +92,7 @@ import org.apache.activemq.artemis.utils.RandomUtil;
 import org.apache.activemq.artemis.utils.SensitiveDataCodec;
 import org.apache.activemq.artemis.utils.StringUtil;
 import org.apache.activemq.artemis.utils.Wait;
+import org.apache.activemq.artemis.utils.XmlProvider;
 import org.apache.commons.configuration2.PropertiesConfiguration;
 import org.apache.commons.configuration2.builder.FileBasedConfigurationBuilder;
 import org.apache.commons.configuration2.builder.fluent.Configurations;
@@ -368,8 +367,7 @@ public class ArtemisTest extends CliTestBase {
       originalBootstrapFile.delete();
 
       // write the modified config into the bootstrap.xml file
-      TransformerFactory transformerFactory = TransformerFactory.newInstance();
-      Transformer transformer = transformerFactory.newTransformer();
+      Transformer transformer = XmlProvider.newTransformer();
       DOMSource source = new DOMSource(config);
       StreamResult streamResult = new StreamResult(originalBootstrapFile);
       transformer.transform(source, streamResult);
@@ -2195,8 +2193,7 @@ public class ArtemisTest extends CliTestBase {
    }
 
    private static Document parseXml(File xmlFile) throws ParserConfigurationException, IOException, SAXException {
-      DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
-      DocumentBuilder domBuilder = domFactory.newDocumentBuilder();
+      DocumentBuilder domBuilder = XmlProvider.newDocumentBuilder();
       return domBuilder.parse(xmlFile);
    }
 
diff --git a/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/XmlProvider.java b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/XmlProvider.java
new file mode 100644
index 0000000000..07ecc95d4e
--- /dev/null
+++ b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/XmlProvider.java
@@ -0,0 +1,265 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.utils;
+
+import javax.xml.XMLConstants;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+import javax.xml.validation.Validator;
+import java.io.InputStream;
+import java.io.Reader;
+import java.net.URL;
+import java.util.Map;
+
+import org.w3c.dom.ls.LSInput;
+import org.xml.sax.SAXException;
+
+public class XmlProvider {
+   public static final String ARTEMIS_DISABLE_XXE_PROPERTY = "artemis.disableXxe";
+
+   public static final String XINCLUDE_AWARE_PROPERTY = "XINCLUDE_AWARE";
+   public static final String NAMESPACE_AWARE_PROPERTY = "NAMESPACE_AWARE";
+   public static final String IGNORE_COMMENTS_PROPERTY = "IGNORE_COMMENTS";
+   public static final String IGNORE_ELEMENT_CONTENT_WHITESPACE_PROPERTY = "IGNORE_ELEMENT_CONTENT_WHITESPACE";
+
+   private static final String ACTIVEMQ_CORE_NS = "urn:activemq:core";
+   private static final String ACTIVEMQ_JMS_NS = "urn:activemq:jms";
+
+   private static final String ARTEMIS_XML_SCHEMA_SID = "xml.xsd";
+   private static final String ARTEMIS_CONFIGURATION_SCHEMA_SID = "artemis-configuration.xsd";
+   private static final String ARTEMIS_JMS_SCHEMA_SID = "artemis-jms.xsd";
+
+   private static final String ARTEMIS_SCHEMA_BASE_URL = "schema/";
+   private static final String ARTEMIS_XML_SCHEMA_URL = ARTEMIS_SCHEMA_BASE_URL + ARTEMIS_XML_SCHEMA_SID;
+   private static final String ARTEMIS_CONFIGURATION_SCHEMA_URL = ARTEMIS_SCHEMA_BASE_URL + ARTEMIS_CONFIGURATION_SCHEMA_SID;
+   private static final String ARTEMIS_JMS_SCHEMA_URL = ARTEMIS_SCHEMA_BASE_URL + ARTEMIS_JMS_SCHEMA_SID;
+
+   private static boolean xxeEnabled = !"".equals(System.getProperty(ARTEMIS_DISABLE_XXE_PROPERTY)) &&
+      !Boolean.parseBoolean(System.getProperty(ARTEMIS_DISABLE_XXE_PROPERTY, Boolean.FALSE.toString()));
+
+   public static boolean isXxeEnabled() {
+      return xxeEnabled;
+   }
+
+   public static void setXxeEnabled(boolean enabled) {
+      xxeEnabled = enabled;
+   }
+
+   public static DocumentBuilder newDocumentBuilder() throws ParserConfigurationException {
+      return newDocumentBuilder(null, null);
+   }
+
+   public static DocumentBuilder newDocumentBuilder(Map<String, Boolean> features, Map<String, Boolean> properties) throws ParserConfigurationException {
+      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+
+      if (features != null) {
+         for (Map.Entry<String, Boolean> feature : features.entrySet()) {
+            factory.setFeature(feature.getKey(), feature.getValue());
+         }
+      }
+
+      if (properties != null) {
+         for (Map.Entry<String, Boolean> property : properties.entrySet()) {
+            if (XINCLUDE_AWARE_PROPERTY.equals(property.getKey())) {
+               factory.setXIncludeAware(property.getValue());
+            } else if (NAMESPACE_AWARE_PROPERTY.equals(property.getKey())) {
+               factory.setNamespaceAware(property.getValue());
+            } else if (IGNORE_COMMENTS_PROPERTY.equals(property.getKey())) {
+               factory.setIgnoringComments(property.getValue());
+            } else if (IGNORE_ELEMENT_CONTENT_WHITESPACE_PROPERTY.equals(property.getKey())) {
+               factory.setIgnoringElementContentWhitespace(property.getValue());
+            } else {
+               throw new IllegalArgumentException("Property not supported: " + property.getKey());
+            }
+         }
+      }
+
+      if (!isXxeEnabled()) {
+         factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
+         factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
+         factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
+         factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
+
+         factory.setXIncludeAware(false);
+         factory.setExpandEntityReferences(false);
+      }
+
+      return factory.newDocumentBuilder();
+   }
+
+   public static XMLStreamReader createXMLStreamReader(InputStream inputStream) throws XMLStreamException {
+      XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
+
+      if (!isXxeEnabled()) {
+         // This disables DTDs entirely for that factory
+         xmlInputFactory.setProperty(XMLInputFactory.SUPPORT_DTD, false);
+         // disable external entities
+         xmlInputFactory.setProperty("javax.xml.stream.isSupportingExternalEntities", false);
+      }
+
+      return xmlInputFactory.createXMLStreamReader(inputStream);
+   }
+
+   public static Schema newSchema(Source schema, Map<String, Boolean> features) throws SAXException {
+      return newSchemaFactory(features).newSchema(schema);
+   }
+
+   private static SchemaFactory newSchemaFactory(Map<String, Boolean> features) throws SAXException {
+      SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+
+      if (features != null) {
+         for (Map.Entry<String, Boolean> feature : features.entrySet()) {
+            factory.setFeature(feature.getKey(), feature.getValue());
+         }
+      }
+
+      if (!isXxeEnabled()) {
+         factory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
+         factory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
+
+         factory.setResourceResolver((type, namespaceURI, publicId, systemId, baseURI) -> {
+            if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(type) && XMLConstants.XML_NS_URI.equals(namespaceURI) && ARTEMIS_XML_SCHEMA_SID.equals(systemId)) {
+               return newLSInput(publicId, systemId, baseURI, Thread.currentThread().getContextClassLoader().getResourceAsStream(ARTEMIS_XML_SCHEMA_URL));
+            } else if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(type) && ACTIVEMQ_CORE_NS.equals(namespaceURI) && ARTEMIS_CONFIGURATION_SCHEMA_SID.equals(systemId)) {
+               return newLSInput(publicId, systemId, baseURI, Thread.currentThread().getContextClassLoader().getResourceAsStream(ARTEMIS_CONFIGURATION_SCHEMA_URL));
+            } else if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(type) && ACTIVEMQ_JMS_NS.equals(namespaceURI) && ARTEMIS_JMS_SCHEMA_SID.equals(systemId)) {
+               return newLSInput(publicId, systemId, baseURI, Thread.currentThread().getContextClassLoader().getResourceAsStream(ARTEMIS_JMS_SCHEMA_URL));
+            }
+
+            return null;
+         });
+      }
+
+      return factory;
+   }
+
+   public static Transformer newTransformer() throws TransformerConfigurationException {
+      TransformerFactory transformerFactory = TransformerFactory.newInstance();
+
+      if (!isXxeEnabled()) {
+         transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
+         transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
+      }
+
+      return transformerFactory.newTransformer();
+   }
+
+   public static Validator newValidator(URL schema) throws SAXException {
+      Validator validator = newSchemaFactory(null).newSchema(schema).newValidator();
+
+      if (!isXxeEnabled()) {
+         validator.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
+         validator.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
+      }
+
+      return validator;
+   }
+
+   private static LSInput newLSInput(String publicId, String systemId, String baseURI, InputStream byteStream) {
+      return new LSInput() {
+         @Override
+         public Reader getCharacterStream() {
+            return null;
+         }
+
+         @Override
+         public void setCharacterStream(Reader reader) {
+
+         }
+
+         @Override
+         public InputStream getByteStream() {
+            return byteStream;
+         }
+
+         @Override
+         public void setByteStream(InputStream inputStream) {
+
+         }
+
+         @Override
+         public String getStringData() {
+            return null;
+         }
+
+         @Override
+         public void setStringData(String s) {
+
+         }
+
+         @Override
+         public String getSystemId() {
+            return systemId;
+         }
+
+         @Override
+         public void setSystemId(String s) {
+
+         }
+
+         @Override
+         public String getPublicId() {
+            return publicId;
+         }
+
+         @Override
+         public void setPublicId(String s) {
+
+         }
+
+         @Override
+         public String getBaseURI() {
+            return baseURI;
+         }
+
+         @Override
+         public void setBaseURI(String s) {
+
+         }
+
+         @Override
+         public String getEncoding() {
+            return null;
+         }
+
+         @Override
+         public void setEncoding(String s) {
+
+         }
+
+         @Override
+         public boolean getCertifiedText() {
+            return false;
+         }
+
+         @Override
+         public void setCertifiedText(boolean b) {
+
+         }
+      };
+   }
+}
diff --git a/artemis-commons/src/test/java/org/apache/activemq/artemis/utils/XmlProviderTest.java b/artemis-commons/src/test/java/org/apache/activemq/artemis/utils/XmlProviderTest.java
new file mode 100644
index 0000000000..989ae50f6e
--- /dev/null
+++ b/artemis-commons/src/test/java/org/apache/activemq/artemis/utils/XmlProviderTest.java
@@ -0,0 +1,134 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.activemq.artemis.utils;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Validator;
+import java.io.File;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+@RunWith(Parameterized.class)
+public class XmlProviderTest {
+
+   @Parameterized.Parameters(name = "xxeEnabled={0}")
+   public static Collection getParameters() {
+      return Arrays.asList(new Boolean[]{true, false});
+   }
+
+   public XmlProviderTest(boolean xxeEnabled) {
+      XmlProvider.setXxeEnabled(xxeEnabled);
+   }
+
+   @Test
+   public void testDocument() throws Exception {
+      DocumentBuilder documentBuilder = XmlProvider.newDocumentBuilder();
+      Document document = documentBuilder.parse(new File(getClass().getResource("/document.xml").toURI()));
+      Element documentElement = document.getDocumentElement();
+
+      Assert.assertEquals("t:book", documentElement.getTagName());
+      Assert.assertEquals(1, documentElement.getElementsByTagName("title").getLength());
+   }
+
+   @Test
+   public void testDocumentWithXmlInclude() throws Exception {
+      Map<String, Boolean> properties = new HashMap<>();
+      properties.put(XmlProvider.XINCLUDE_AWARE_PROPERTY, true);
+      properties.put(XmlProvider.NAMESPACE_AWARE_PROPERTY, true);
+      DocumentBuilder documentBuilder = XmlProvider.newDocumentBuilder(null, properties);
+      Document document = documentBuilder.parse(new File(XmlProviderTest.class.getResource("/document-with-xinclude.xml").toURI()));
+      Element documentElement = document.getDocumentElement();
+
+      Assert.assertEquals("t:book", documentElement.getTagName());
+
+      if (XmlProvider.isXxeEnabled()) {
+         Assert.assertEquals(1, documentElement.getElementsByTagName("title").getLength());
+      } else {
+         Assert.assertEquals(0, documentElement.getElementsByTagName("title").getLength());
+      }
+   }
+
+   @Test
+   public void testSchema() throws Exception {
+      StreamSource streamSource = new StreamSource(XmlProviderTest.class.getResourceAsStream("/schema.xsd"));
+      XmlProvider.newSchema(streamSource, null);
+   }
+
+   @Test
+   public void testSchemaWithImport() {
+      StreamSource streamSource = new StreamSource(XmlProviderTest.class.getResourceAsStream("/schema-with-import.xsd"));
+
+      Exception newSchemaException = null;
+      try {
+         XmlProvider.newSchema(streamSource, null);
+      } catch (Exception e) {
+         newSchemaException = e;
+      }
+
+      if (XmlProvider.isXxeEnabled()) {
+         Assert.assertNull(newSchemaException);
+      } else {
+         Assert.assertNotNull(newSchemaException);
+      }
+   }
+
+   @Test
+   public void testValidator() throws Exception {
+      Map<String, Boolean> properties = new HashMap<>();
+      properties.put(XmlProvider.NAMESPACE_AWARE_PROPERTY, true);
+      DocumentBuilder documentBuilder = XmlProvider.newDocumentBuilder(null, properties);
+      Document document = documentBuilder.parse(new File(getClass().getResource("/document.xml").toURI()));
+      Element documentElement = document.getDocumentElement();
+
+      Validator validator = XmlProvider.newValidator(XmlProviderTest.class.getResource("/schema.xsd"));
+      validator.validate(new DOMSource(documentElement));
+   }
+
+   @Test
+   public void testValidatorWithImport() throws Exception {
+      Map<String, Boolean> properties = new HashMap<>();
+      properties.put(XmlProvider.NAMESPACE_AWARE_PROPERTY, true);
+      DocumentBuilder documentBuilder = XmlProvider.newDocumentBuilder(null, properties);
+      Document document = documentBuilder.parse(new File(getClass().getResource("/document.xml").toURI()));
+      Element documentElement = document.getDocumentElement();
+
+      Exception validateException = null;
+      try {
+         Validator validator = XmlProvider.newValidator(XmlProviderTest.class.getResource("/schema-with-import.xsd"));
+         validator.validate(new DOMSource(documentElement));
+      } catch (Exception e) {
+         validateException = e;
+      }
+
+      if (XmlProvider.isXxeEnabled()) {
+         Assert.assertNull(validateException);
+      } else {
+         Assert.assertNotNull(validateException);
+      }
+   }
+}
diff --git a/artemis-commons/src/test/resources/document-with-xinclude-title.xml b/artemis-commons/src/test/resources/document-with-xinclude-title.xml
new file mode 100644
index 0000000000..f6dca7ce18
--- /dev/null
+++ b/artemis-commons/src/test/resources/document-with-xinclude-title.xml
@@ -0,0 +1,17 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<title>document</title>
diff --git a/artemis-commons/src/test/resources/document-with-xinclude.xml b/artemis-commons/src/test/resources/document-with-xinclude.xml
new file mode 100644
index 0000000000..16aa9438cc
--- /dev/null
+++ b/artemis-commons/src/test/resources/document-with-xinclude.xml
@@ -0,0 +1,19 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<t:book xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:t="urn:test">
+   <xi:include href="document-with-xinclude-title.xml"/>
+</t:book>
diff --git a/artemis-commons/src/test/resources/document.xml b/artemis-commons/src/test/resources/document.xml
new file mode 100644
index 0000000000..fab35079cf
--- /dev/null
+++ b/artemis-commons/src/test/resources/document.xml
@@ -0,0 +1,19 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<t:book xmlns:t="urn:test">
+   <title>test</title>
+</t:book>
diff --git a/artemis-commons/src/test/resources/schema-with-import.xsd b/artemis-commons/src/test/resources/schema-with-import.xsd
new file mode 100644
index 0000000000..548562c77a
--- /dev/null
+++ b/artemis-commons/src/test/resources/schema-with-import.xsd
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+   <xs:import namespace="urn:test" schemaLocation="schema.xsd"/>
+</xs:schema>
diff --git a/artemis-commons/src/test/resources/schema.xsd b/artemis-commons/src/test/resources/schema.xsd
new file mode 100644
index 0000000000..f236629e40
--- /dev/null
+++ b/artemis-commons/src/test/resources/schema.xsd
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<xs:schema targetNamespace="urn:test" xmlns:xs="http://www.w3.org/2001/XMLSchema">
+   <xs:element name="book">
+      <xs:complexType>
+         <xs:sequence>
+            <xs:element name="title" type="xs:string"/>
+         </xs:sequence>
+      </xs:complexType>
+   </xs:element>
+</xs:schema>
diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/utils/XMLUtil.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/utils/XMLUtil.java
index f28b83a902..fd3c940d39 100644
--- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/utils/XMLUtil.java
+++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/utils/XMLUtil.java
@@ -16,12 +16,8 @@
  */
 package org.apache.activemq.artemis.utils;
 
-import javax.xml.XMLConstants;
 import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.transform.dom.DOMSource;
-import javax.xml.validation.Schema;
-import javax.xml.validation.SchemaFactory;
 import javax.xml.validation.Validator;
 import java.io.InputStream;
 import java.io.InputStreamReader;
@@ -31,6 +27,7 @@ import java.net.URL;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 
 import org.apache.activemq.artemis.core.client.ActiveMQClientLogger;
@@ -38,6 +35,8 @@ import org.apache.activemq.artemis.core.client.ActiveMQClientMessageBundle;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import java.lang.invoke.MethodHandles;
+import java.util.Map;
+
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.NamedNodeMap;
@@ -85,10 +84,10 @@ public final class XMLUtil {
    }
 
    public static Element readerToElement(final Reader r) throws Exception {
-      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
-      factory.setNamespaceAware(true);
-      factory.setXIncludeAware(true);
-      DocumentBuilder parser = factory.newDocumentBuilder();
+      Map<String, Boolean> properties = new HashMap<>();
+      properties.put(XmlProvider.XINCLUDE_AWARE_PROPERTY, true);
+      properties.put(XmlProvider.NAMESPACE_AWARE_PROPERTY, true);
+      DocumentBuilder parser = XmlProvider.newDocumentBuilder(null, properties);
       Document doc = replaceSystemPropsInXml(parser.parse(new InputSource(new StringReader(replaceSystemPropsInString(readerToString(r))))));
       return doc.getDocumentElement();
    }
@@ -366,10 +365,7 @@ public final class XMLUtil {
    }
 
    public static void validate(final Node node, final String schemaFile) throws Exception {
-      SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
-
-      Schema schema = factory.newSchema(new URL(findResource(schemaFile).toURI().toASCIIString()));
-      Validator validator = schema.newValidator();
+      Validator validator = XmlProvider.newValidator(new URL(findResource(schemaFile).toURI().toASCIIString()));
 
       // validate the DOM tree
       try {
diff --git a/artemis-dto/src/main/java/org/apache/activemq/artemis/dto/XmlUtil.java b/artemis-dto/src/main/java/org/apache/activemq/artemis/dto/XmlUtil.java
index 8ed7642458..5bcfb0216b 100644
--- a/artemis-dto/src/main/java/org/apache/activemq/artemis/dto/XmlUtil.java
+++ b/artemis-dto/src/main/java/org/apache/activemq/artemis/dto/XmlUtil.java
@@ -16,23 +16,23 @@
  */
 package org.apache.activemq.artemis.dto;
 
-import javax.xml.XMLConstants;
 import javax.xml.bind.JAXBContext;
 import javax.xml.bind.Unmarshaller;
-import javax.xml.stream.XMLInputFactory;
 import javax.xml.stream.XMLStreamReader;
 import javax.xml.stream.util.StreamReaderDelegate;
 import javax.xml.transform.stream.StreamSource;
 import javax.xml.validation.Schema;
-import javax.xml.validation.SchemaFactory;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.InputStream;
 import java.net.URI;
+import java.util.Collections;
 import java.util.Properties;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import org.apache.activemq.artemis.utils.XmlProvider;
+
 public class XmlUtil {
 
    /**
@@ -73,8 +73,6 @@ public class XmlUtil {
 
    }
 
-   private static final XMLInputFactory factory = XMLInputFactory.newInstance();
-
    public static <T> T decode(Class<T> clazz, File configuration) throws Exception {
       return decode(clazz, configuration, null, null, null);
    }
@@ -90,11 +88,10 @@ public class XmlUtil {
       JAXBContext jaxbContext = JAXBContext.newInstance("org.apache.activemq.artemis.dto");
 
       Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
-      SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
-      sf.setFeature("http://apache.org/xml/features/validation/schema-full-checking", false);
       InputStream xsdStream = XmlUtil.class.getClassLoader().getResourceAsStream("org.apache.activemq/dto/activemq.xsd");
       StreamSource xsdSource = new StreamSource(xsdStream);
-      Schema schema = sf.newSchema(xsdSource);
+      Schema schema = XmlProvider.newSchema(xsdSource, Collections.singletonMap(
+         "http://apache.org/xml/features/validation/schema-full-checking", false));
       unmarshaller.setSchema(schema);
 
       Properties props = new Properties(System.getProperties());
@@ -110,7 +107,7 @@ public class XmlUtil {
          props.put("artemis.URI.instance", artemisURIInstance.toString());
       }
 
-      XMLStreamReader reader = factory.createXMLStreamReader(new FileInputStream(configuration));
+      XMLStreamReader reader = XmlProvider.createXMLStreamReader(new FileInputStream(configuration));
 
       reader = new PropertiesFilter(reader, props);
 
diff --git a/artemis-selector/src/main/java/org/apache/activemq/artemis/selector/filter/XPathExpression.java b/artemis-selector/src/main/java/org/apache/activemq/artemis/selector/filter/XPathExpression.java
index d0fe8364d8..200466f6cd 100755
--- a/artemis-selector/src/main/java/org/apache/activemq/artemis/selector/filter/XPathExpression.java
+++ b/artemis-selector/src/main/java/org/apache/activemq/artemis/selector/filter/XPathExpression.java
@@ -17,11 +17,13 @@
 package org.apache.activemq.artemis.selector.filter;
 
 import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
+import java.util.HashMap;
 import java.util.Map;
 import java.util.Properties;
 
+import org.apache.activemq.artemis.utils.XmlProvider;
+
 /**
  * Used to evaluate an XPath Expression in a JMS selector.
  */
@@ -36,19 +38,14 @@ public final class XPathExpression implements BooleanExpression {
    public static final String DOCUMENT_BUILDER_FACTORY_FEATURE_PREFIX = "org.apache.activemq.documentBuilderFactory.feature:";
 
    static {
-      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
-      factory.setNamespaceAware(true);
-      factory.setIgnoringElementContentWhitespace(true);
-      factory.setIgnoringComments(true);
-
       try {
-         factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
-         factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
-         factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
-
-         // setup features from system properties (if any)
-         setupFeatures(factory);
-         builder = factory.newDocumentBuilder();
+         // get features from system properties (if any)
+         Map<String, Boolean> features = getFeatures();
+         Map<String, Boolean> properties = new HashMap<>();
+         properties.put(XmlProvider.NAMESPACE_AWARE_PROPERTY, true);
+         properties.put(XmlProvider.IGNORE_COMMENTS_PROPERTY, true);
+         properties.put(XmlProvider.IGNORE_ELEMENT_CONTENT_WHITESPACE_PROPERTY, true);
+         builder = XmlProvider.newDocumentBuilder(features, properties);
       } catch (ParserConfigurationException e) {
          throw new RuntimeException(e);
       }
@@ -97,14 +94,16 @@ public final class XPathExpression implements BooleanExpression {
       return object == Boolean.TRUE;
    }
 
-   protected static void setupFeatures(DocumentBuilderFactory factory) throws ParserConfigurationException {
+   protected static Map<String, Boolean> getFeatures() throws ParserConfigurationException {
+      Map<String, Boolean> features = new HashMap<>();
       Properties properties = System.getProperties();
       for (Map.Entry<Object, Object> prop : properties.entrySet()) {
          String key = (String) prop.getKey();
          if (key.startsWith(DOCUMENT_BUILDER_FACTORY_FEATURE_PREFIX)) {
             Boolean value = Boolean.valueOf((String)prop.getValue());
-            factory.setFeature(key.substring(DOCUMENT_BUILDER_FACTORY_FEATURE_PREFIX.length()), value);
+            features.put(key.substring(DOCUMENT_BUILDER_FACTORY_FEATURE_PREFIX.length()), value);
          }
       }
+      return features;
    }
 }
diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/deployers/impl/FileConfigurationParser.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/deployers/impl/FileConfigurationParser.java
index 4abeda8ab1..f41b770290 100644
--- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/deployers/impl/FileConfigurationParser.java
+++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/deployers/impl/FileConfigurationParser.java
@@ -16,10 +16,7 @@
  */
 package org.apache.activemq.artemis.core.deployers.impl;
 
-import javax.xml.XMLConstants;
 import javax.xml.transform.dom.DOMSource;
-import javax.xml.validation.Schema;
-import javax.xml.validation.SchemaFactory;
 import javax.xml.validation.Validator;
 import java.io.InputStream;
 import java.security.AccessController;
@@ -110,6 +107,7 @@ import org.apache.activemq.artemis.utils.DefaultSensitiveStringCodec;
 import org.apache.activemq.artemis.utils.PasswordMaskingUtil;
 import org.apache.activemq.artemis.utils.XMLConfigurationUtil;
 import org.apache.activemq.artemis.utils.XMLUtil;
+import org.apache.activemq.artemis.utils.XmlProvider;
 import org.apache.activemq.artemis.utils.critical.CriticalAnalyzerPolicy;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -354,9 +352,7 @@ public final class FileConfigurationParser extends XMLConfigurationUtil {
 
    public Configuration parseMainConfig(final InputStream input) throws Exception {
       Element e = XMLUtil.streamToElement(input);
-      SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
-      Schema schema = schemaFactory.newSchema(XMLUtil.findResource("schema/artemis-server.xsd"));
-      Validator validator = schema.newValidator();
+      Validator validator = XmlProvider.newValidator(XMLUtil.findResource("schema/artemis-server.xsd"));
       try {
          validator.validate(new DOMSource(e));
       } catch (Exception ex) {
diff --git a/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/FileConfigurationTest.java b/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/FileConfigurationTest.java
index 86a2b347ab..67ed32c16f 100644
--- a/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/FileConfigurationTest.java
+++ b/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/FileConfigurationTest.java
@@ -22,6 +22,8 @@ import java.net.URLClassLoader;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.StandardCopyOption;
+import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
@@ -72,12 +74,16 @@ import org.apache.activemq.artemis.core.settings.impl.SlowConsumerPolicy;
 import org.apache.activemq.artemis.core.settings.impl.SlowConsumerThresholdMeasurementUnit;
 import org.apache.activemq.artemis.logs.AssertionLoggerHandler;
 import org.apache.activemq.artemis.utils.RandomUtil;
+import org.apache.activemq.artemis.utils.XmlProvider;
 import org.apache.activemq.artemis.utils.critical.CriticalAnalyzerPolicy;
 import org.junit.AfterClass;
 import org.junit.Assert;
 import org.junit.BeforeClass;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
 
+@RunWith(Parameterized.class)
 public class FileConfigurationTest extends ConfigurationImplTest {
 
    @BeforeClass
@@ -96,6 +102,15 @@ public class FileConfigurationTest extends ConfigurationImplTest {
       System.clearProperty("ninetyTwoProp");
    }
 
+   @Parameterized.Parameters(name = "xxeEnabled={0}")
+   public static Collection getParameters() {
+      return Arrays.asList(new Boolean[] {true, false});
+   }
+
+   public FileConfigurationTest(boolean xxeEnabled) {
+      XmlProvider.setXxeEnabled(xxeEnabled);
+   }
+
    protected String getConfigurationName() {
       return "ConfigurationTest-full-config.xml";
    }
diff --git a/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/FileXIncludeConfigurationTest.java b/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/FileXIncludeConfigurationTest.java
index acd0256eb4..8206ba91f9 100644
--- a/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/FileXIncludeConfigurationTest.java
+++ b/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/FileXIncludeConfigurationTest.java
@@ -17,10 +17,16 @@
 package org.apache.activemq.artemis.core.config.impl;
 
 import org.junit.AfterClass;
+import org.junit.Assume;
 import org.junit.BeforeClass;
 
 public class FileXIncludeConfigurationTest extends FileConfigurationTest {
 
+   public FileXIncludeConfigurationTest(boolean xxeEnabled) {
+      super(xxeEnabled);
+      Assume.assumeTrue(xxeEnabled);
+   }
+
    @BeforeClass
    public static void setupProperties() {
       System.setProperty("xincludePath", "./src/test/resources");
diff --git a/docs/user-manual/en/configuration-index.md b/docs/user-manual/en/configuration-index.md
index 4ff0542172..26a677a0bd 100644
--- a/docs/user-manual/en/configuration-index.md
+++ b/docs/user-manual/en/configuration-index.md
@@ -46,6 +46,11 @@ For further information on XInclude see:
 
 [https://www.w3.org/TR/xinclude/](https://www.w3.org/TR/xinclude/)
 
+To disable XML external entity processing use the system property `artemis.disableXxe`, e.g.:
+```
+-Dartemis.disableXxe=true
+```
+
 ##### Reloading modular configuration files
 
 Certain changes in `broker.xml` can be picked up at runtime as discussed in the [Configuration Reload](config-reload.md)
diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/XmlExportTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/XmlExportTest.java
index a56bc0155d..2ea08336d3 100644
--- a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/XmlExportTest.java
+++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/XmlExportTest.java
@@ -16,7 +16,6 @@
  */
 package org.apache.activemq.artemis.tests.integration.amqp;
 
-import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.xpath.XPathConstants;
 import javax.xml.xpath.XPathFactory;
 import java.io.ByteArrayInputStream;
@@ -24,6 +23,7 @@ import java.io.ByteArrayOutputStream;
 
 import org.apache.activemq.artemis.cli.commands.tools.xml.XmlDataExporter;
 import org.apache.activemq.artemis.protocol.amqp.converter.AMQPMessageSupport;
+import org.apache.activemq.artemis.utils.XmlProvider;
 import org.apache.activemq.transport.amqp.client.AmqpClient;
 import org.apache.activemq.transport.amqp.client.AmqpConnection;
 import org.apache.activemq.transport.amqp.client.AmqpMessage;
@@ -59,7 +59,7 @@ public class XmlExportTest extends AmqpClientTestSupport {
                               server.getConfiguration().getPagingDirectory(),
                               server.getConfiguration().getLargeMessagesDirectory());
 
-      Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().
+      Document document = XmlProvider.newDocumentBuilder().
          parse(new ByteArrayInputStream(xmlOutputStream.toByteArray()));
 
       Assert.assertNotNull(XPathFactory.newInstance().newXPath().
diff --git a/tests/unit-tests/src/test/java/org/apache/activemq/artemis/tests/unit/ra/ActiveMQResourceAdapterConfigTest.java b/tests/unit-tests/src/test/java/org/apache/activemq/artemis/tests/unit/ra/ActiveMQResourceAdapterConfigTest.java
index 4ee1de6f8f..8a0b86e7a1 100644
--- a/tests/unit-tests/src/test/java/org/apache/activemq/artemis/tests/unit/ra/ActiveMQResourceAdapterConfigTest.java
+++ b/tests/unit-tests/src/test/java/org/apache/activemq/artemis/tests/unit/ra/ActiveMQResourceAdapterConfigTest.java
@@ -17,7 +17,6 @@
 package org.apache.activemq.artemis.tests.unit.ra;
 
 import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
 import java.io.ByteArrayInputStream;
 import java.io.InputStream;
 import java.lang.reflect.Method;
@@ -26,6 +25,7 @@ import java.util.Map;
 
 import org.apache.activemq.artemis.ra.ActiveMQResourceAdapter;
 import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
+import org.apache.activemq.artemis.utils.XmlProvider;
 import org.junit.Test;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -443,8 +443,7 @@ public class ActiveMQResourceAdapterConfigTest extends ActiveMQTestBase {
             methodList.put(method.getName(), method);
          }
       }
-      DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
-      DocumentBuilder db = dbf.newDocumentBuilder();
+      DocumentBuilder db = XmlProvider.newDocumentBuilder();
       InputStream io = new ByteArrayInputStream(rootConfig.getBytes());
       Document dom = db.parse(new InputSource(io));