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

jbonofre pushed a commit to branch activemq-6.1.x
in repository https://gitbox.apache.org/repos/asf/activemq.git


The following commit(s) were added to refs/heads/activemq-6.1.x by this push:
     new a8dad110d7 [AMQ-9783] Centralize XML safe parsing settings in a single 
class. (#1508)
a8dad110d7 is described below

commit a8dad110d7141b8b80dcf7f84fb1ab30c24dda2b
Author: Sérgio Lemos <[email protected]>
AuthorDate: Fri Oct 17 08:35:57 2025 -0700

    [AMQ-9783] Centralize XML safe parsing settings in a single class. (#1508)
---
 .../org/apache/activemq/util/XmlFactories.java     | 76 ++++++++++++++++++++++
 .../activemq/console/command/CreateCommand.java    | 19 ++----
 .../plugin/RuntimeConfigurationBroker.java         |  5 +-
 3 files changed, 84 insertions(+), 16 deletions(-)

diff --git 
a/activemq-broker/src/main/java/org/apache/activemq/util/XmlFactories.java 
b/activemq-broker/src/main/java/org/apache/activemq/util/XmlFactories.java
new file mode 100644
index 0000000000..bef972c96c
--- /dev/null
+++ b/activemq-broker/src/main/java/org/apache/activemq/util/XmlFactories.java
@@ -0,0 +1,76 @@
+/**
+ * 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.util;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.xml.XMLConstants;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerFactory;
+
+/**
+ * Utility class to obtain XML-processing related factories with 
pre-configured safe parameters. Prefer to centralize
+ * these parameters here instead of doing ad-hoc on several places.
+ */
+public final class XmlFactories {
+    private static final Logger LOG = 
LoggerFactory.getLogger(XmlFactories.class);
+
+    private XmlFactories() { /* Do not instantiate */ }
+
+    public static DocumentBuilderFactory getSafeDocumentBuilderFactory() {
+        DocumentBuilderFactory builderFactory = 
DocumentBuilderFactory.newInstance();
+
+        // See 
https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.md#java
+        trySetFeature(builderFactory, XMLConstants.FEATURE_SECURE_PROCESSING, 
true);
+        
trySetFeature(builderFactory,"http://apache.org/xml/features/disallow-doctype-decl";,
 true);
+        
trySetFeature(builderFactory,"http://xml.org/sax/features/external-general-entities";,
 false);
+        
trySetFeature(builderFactory,"http://xml.org/sax/features/external-parameter-entities";,
 false);
+        
trySetFeature(builderFactory,"http://apache.org/xml/features/nonvalidating/load-external-dtd";,
 false);
+
+        return builderFactory;
+    }
+
+    public static TransformerFactory getSafeTransformFactory() {
+        TransformerFactory transformerFactory = 
TransformerFactory.newInstance();
+        trySetFeature(transformerFactory, 
XMLConstants.FEATURE_SECURE_PROCESSING, true);
+
+        // See 
https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.md#transformerfactory
+        transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
+        
transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
+
+        return transformerFactory;
+    }
+
+    private static void trySetFeature(final DocumentBuilderFactory factory, 
final String name, final boolean value) {
+        try {
+            factory.setFeature(name, value);
+        } catch (final ParserConfigurationException e) {
+            LOG.warn("Error setting document builder factory feature", e);
+        }
+    }
+
+    private static void trySetFeature(final TransformerFactory factory, final 
String name, final boolean value) {
+        try {
+            factory.setFeature(name, value);
+        } catch (final TransformerConfigurationException e) {
+            LOG.warn("Error setting transformer factory feature", e);
+        }
+    }
+}
diff --git 
a/activemq-console/src/main/java/org/apache/activemq/console/command/CreateCommand.java
 
b/activemq-console/src/main/java/org/apache/activemq/console/command/CreateCommand.java
index c1c8685f45..f976b4ee10 100644
--- 
a/activemq-console/src/main/java/org/apache/activemq/console/command/CreateCommand.java
+++ 
b/activemq-console/src/main/java/org/apache/activemq/console/command/CreateCommand.java
@@ -16,13 +16,12 @@
  */
 package org.apache.activemq.console.command;
 
+import org.apache.activemq.util.XmlFactories;
 import org.w3c.dom.Attr;
 import org.w3c.dom.Element;
 import org.xml.sax.SAXException;
 
-import javax.xml.XMLConstants;
 import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.transform.*;
 import javax.xml.transform.dom.DOMSource;
@@ -159,10 +158,7 @@ public class CreateCommand extends AbstractCommand {
         File dest = new File(targetBase, DEFAULT_TARGET_ACTIVEMQ_CONF);
         context.print("Copying from: " + src.getCanonicalPath() + "\n          
to: " + dest.getCanonicalPath());
 
-        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
-        dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, Boolean.TRUE);
-        dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl";, 
true);
-        DocumentBuilder builder = dbf.newDocumentBuilder();
+        DocumentBuilder builder = 
XmlFactories.getSafeDocumentBuilderFactory().newDocumentBuilder();
         Element docElem = builder.parse(src).getDocumentElement();
 
         XPath xpath = XPathFactory.newInstance().newXPath();
@@ -208,13 +204,10 @@ public class CreateCommand extends AbstractCommand {
 
     // utlity method to write an xml source to file
     private void writeToFile(Source src, File file) throws 
TransformerException {
-        TransformerFactory tFactory = TransformerFactory.newInstance();
-        tFactory.setFeature(javax.xml.XMLConstants.FEATURE_SECURE_PROCESSING, 
Boolean.TRUE);
-
-        Transformer fileTransformer = tFactory.newTransformer();
-
-        Result res = new StreamResult(file);
-        fileTransformer.transform(src, res);
+        final Result res = new StreamResult(file);
+        XmlFactories.getSafeTransformFactory()
+                .newTransformer()
+                .transform(src, res);
     }
 
     // utility method to copy one file to another
diff --git 
a/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/RuntimeConfigurationBroker.java
 
b/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/RuntimeConfigurationBroker.java
index b7342f417d..27fd410c64 100644
--- 
a/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/RuntimeConfigurationBroker.java
+++ 
b/activemq-runtime-config/src/main/java/org/apache/activemq/plugin/RuntimeConfigurationBroker.java
@@ -42,6 +42,7 @@ import org.apache.activemq.broker.jmx.ManagementContext;
 import org.apache.activemq.plugin.jmx.RuntimeConfigurationView;
 import org.apache.activemq.schema.core.DtoBroker;
 import org.apache.activemq.spring.Utils;
+import org.apache.activemq.util.XmlFactories;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.core.io.Resource;
@@ -178,10 +179,8 @@ public class RuntimeConfigurationBroker extends 
AbstractRuntimeConfigurationBrok
                 unMarshaller.setSchema(getSchema());
 
                 // skip beans and pull out the broker node to validate
-                DocumentBuilderFactory dbf = 
DocumentBuilderFactory.newInstance();
+                DocumentBuilderFactory dbf = 
XmlFactories.getSafeDocumentBuilderFactory();
                 dbf.setNamespaceAware(true);
-                dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, 
Boolean.TRUE);
-                
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl";, true);
 
                 DocumentBuilder db = dbf.newDocumentBuilder();
                 Document doc = db.parse(configToMonitor.getInputStream());


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]
For further information, visit: https://activemq.apache.org/contact


Reply via email to