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

tballison pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tika.git


The following commit(s) were added to refs/heads/main by this push:
     new f7173fe3ca TIKA-4940: retire Tika's XML entity expansion limit (#3268)
f7173fe3ca is described below

commit f7173fe3caba99b0904b9124ce6304476d034e95
Author: Tim Allison <[email protected]>
AuthorDate: Mon Sep 28 15:44:48 2026 -0400

    TIKA-4940: retire Tika's XML entity expansion limit (#3268)
---
 .gitignore                                         |   2 -
 CHANGES.txt                                        |   5 +-
 .../java/org/apache/tika/utils/XMLReaderUtils.java | 274 ++-------------------
 .../org/apache/tika/utils/XMLReaderUtilsTest.java  |  33 +++
 .../org/apache/tika/config/loader/TikaLoader.java  |   5 +-
 .../tika/serialization/config/GlobalSettings.java  |   6 +-
 6 files changed, 70 insertions(+), 255 deletions(-)

diff --git a/.gitignore b/.gitignore
index 00c9477de0..77ae19c8fa 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,7 +3,6 @@ target
 dependency-reduced-pom.xml
 .idea
 .classpath
-.checkstyle
 .project
 .settings
 *.iml
@@ -27,5 +26,4 @@ tika-grpc/ignite
 __pycache__/
 *.pyc
 
-_remote.repositories
 /.local_m2_repo/
diff --git a/CHANGES.txt b/CHANGES.txt
index d87c2a0cbf..4e6124d596 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,5 +1,8 @@
-Release 4.1.1 - unreleased
+Release 4.2.0 - unreleased
 
+   * Retire Tika's entity expansion limit (default 20) in SAX, DOM and StAX
+     parsing in favor of standard Java configuration methods (TIKA-4940).
+   
    * Deprecate XMLReaderUtils.getXMLInputFactory() and use SAX for XFA 
(TIKA-4938).
 
 Release 4.1.0 - 9/26/2026
diff --git a/tika-core/src/main/java/org/apache/tika/utils/XMLReaderUtils.java 
b/tika-core/src/main/java/org/apache/tika/utils/XMLReaderUtils.java
index 6ee4b4f26c..da1119f088 100644
--- a/tika-core/src/main/java/org/apache/tika/utils/XMLReaderUtils.java
+++ b/tika-core/src/main/java/org/apache/tika/utils/XMLReaderUtils.java
@@ -21,11 +21,9 @@ import java.io.InputStream;
 import java.io.Reader;
 import java.io.Serializable;
 import java.io.StringReader;
-import java.lang.reflect.Method;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.concurrent.ArrayBlockingQueue;
-import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
@@ -75,6 +73,11 @@ public class XMLReaderUtils implements Serializable {
      * and the pool of DOM builders
      */
     public static final int DEFAULT_POOL_SIZE = 10;
+    /**
+     * @deprecated since 4.2.0, removal planned for 5.0; Tika no longer sets 
an entity
+     * expansion limit. The JAXP provider's secure-processing limits apply.
+     */
+    @Deprecated
     public static final int DEFAULT_MAX_ENTITY_EXPANSIONS = 20;
     public static final int DEFAULT_NUM_REUSES = 100;
     /**
@@ -82,11 +85,7 @@ public class XMLReaderUtils implements Serializable {
      */
     private static final long serialVersionUID = 6110455808615143122L;
     private static final Logger LOG = 
LoggerFactory.getLogger(XMLReaderUtils.class);
-    private static final String XERCES_SECURITY_MANAGER = 
"org.apache.xerces.util.SecurityManager";
-    private static final String XERCES_SECURITY_MANAGER_PROPERTY =
-            "http://apache.org/xml/properties/security-manager";;
-
-    private static final AtomicBoolean HAS_WARNED_STAX = new 
AtomicBoolean(false);
+    private static final AtomicBoolean HAS_WARNED_ENTITY_LIMIT = new 
AtomicBoolean(false);
     private static final ContentHandler IGNORING_CONTENT_HANDLER = new 
DefaultHandler();
     private static final DTDHandler IGNORING_DTD_HANDLER = new DTDHandler() {
         @Override
@@ -117,7 +116,6 @@ public class XMLReaderUtils implements Serializable {
 
         }
     };
-    private static final String JAXP_ENTITY_EXPANSION_LIMIT_KEY = 
"jdk.xml.entityExpansionLimit";
     //TODO: figure out if the rw lock is any better than a simple lock
     //these lock the pool arrayblocking queues so that there isn't a race 
condition
     //of trying to acquire a parser while the pool is being resized
@@ -132,8 +130,6 @@ public class XMLReaderUtils implements Serializable {
      */
     private static int POOL_SIZE = DEFAULT_POOL_SIZE;
     private static int MAX_NUM_REUSES = DEFAULT_NUM_REUSES;
-    private static long LAST_LOG = -1;
-    private static volatile int MAX_ENTITY_EXPANSIONS = 
determineMaxEntityExpansions();
     private static ArrayBlockingQueue<PoolSAXParser> SAX_PARSERS =
             new ArrayBlockingQueue<>(POOL_SIZE);
     private static ArrayBlockingQueue<PoolDOMBuilder> DOM_BUILDERS =
@@ -147,21 +143,6 @@ public class XMLReaderUtils implements Serializable {
         }
     }
 
-    private static int determineMaxEntityExpansions() {
-        String expansionLimit = 
System.getProperty(JAXP_ENTITY_EXPANSION_LIMIT_KEY);
-        if (expansionLimit != null) {
-            try {
-                return Integer.parseInt(expansionLimit);
-            } catch (NumberFormatException e) {
-                LOG.warn(
-                        "Couldn't parse an integer for the entity expansion 
limit: {}; " +
-                                "backing off to default: {}",
-                        expansionLimit, DEFAULT_MAX_ENTITY_EXPANSIONS);
-            }
-        }
-        return DEFAULT_MAX_ENTITY_EXPANSIONS;
-    }
-
     /**
      * Returns the XMLReader specified in this parsing context. If a reader
      * is not explicitly specified, then one is created using the specified
@@ -199,9 +180,7 @@ public class XMLReaderUtils implements Serializable {
      */
     public static SAXParser getSAXParser() throws TikaException {
         try {
-            SAXParser parser = getSAXParserFactory().newSAXParser();
-            trySetXercesSecurityManager(parser);
-            return parser;
+            return getSAXParserFactory().newSAXParser();
         } catch (ParserConfigurationException e) {
             throw new TikaException("Unable to configure a SAX parser", e);
         } catch (SAXException e) {
@@ -247,8 +226,6 @@ public class XMLReaderUtils implements Serializable {
 
         factory.setExpandEntityReferences(false);
         factory.setValidating(false);
-
-        trySetXercesSecurityManager(factory);
         return factory;
     }
 
@@ -293,8 +270,6 @@ public class XMLReaderUtils implements Serializable {
 
         //try to cause DTDs to throw exceptions
         tryToSetStaxProperty(factory, XMLInputFactory.SUPPORT_DTD, false);
-
-        trySetStaxSecurityManager(factory);
         return factory;
     }
 
@@ -733,111 +708,6 @@ public class XMLReaderUtils implements Serializable {
         }
     }
 
-    private static void trySetXercesSecurityManager(DocumentBuilderFactory 
factory) {
-        //from POI
-        // Try built-in JVM one first, standalone if not
-        for (String securityManagerClassName : new String[]{
-                //"com.sun.org.apache.xerces.internal.util.SecurityManager",
-                XERCES_SECURITY_MANAGER}) {
-            try {
-                Object mgr =
-                        
Class.forName(securityManagerClassName).getDeclaredConstructor().newInstance();
-                Method setLimit = 
mgr.getClass().getMethod("setEntityExpansionLimit",
-                        Integer.TYPE);
-                setLimit.invoke(mgr, MAX_ENTITY_EXPANSIONS);
-                factory.setAttribute(XERCES_SECURITY_MANAGER_PROPERTY, mgr);
-                // Stop once one can be setup without error
-                return;
-            } catch (ClassNotFoundException e) {
-                // continue without log, this is expected in some setups
-            } catch (Throwable e) {     // NOSONAR - also catch things like 
NoClassDefError here
-                // throttle the log somewhat as it can spam the log otherwise
-                if (System.currentTimeMillis() > LAST_LOG + 
TimeUnit.MINUTES.toMillis(5)) {
-                    LOG.warn(
-                            "SAX Security Manager could not be setup [log 
suppressed for 5 " +
-                                    "minutes]",
-                            e);
-                    LAST_LOG = System.currentTimeMillis();
-                }
-            }
-        }
-
-        // separate old version of Xerces not found => use the builtin way of 
setting the property
-        try {
-            
factory.setAttribute("http://www.oracle.com/xml/jaxp/properties/entityExpansionLimit";,
-                    MAX_ENTITY_EXPANSIONS);
-        } catch (IllegalArgumentException e) {
-            // NOSONAR - also catch things like NoClassDefError here
-            // throttle the log somewhat as it can spam the log otherwise
-            if (System.currentTimeMillis() > LAST_LOG + 
TimeUnit.MINUTES.toMillis(5)) {
-                LOG.warn("SAX Security Manager could not be setup [log 
suppressed for 5 minutes]",
-                        e);
-                LAST_LOG = System.currentTimeMillis();
-            }
-        }
-    }
-
-    private static void trySetXercesSecurityManager(SAXParser parser) {
-        //from POI
-        // Try built-in JVM one first, standalone if not
-        for (String securityManagerClassName : new String[]{
-                //"com.sun.org.apache.xerces.internal.util.SecurityManager",
-                XERCES_SECURITY_MANAGER}) {
-            try {
-                Object mgr =
-                        
Class.forName(securityManagerClassName).getDeclaredConstructor().newInstance();
-                Method setLimit = 
mgr.getClass().getMethod("setEntityExpansionLimit", Integer.TYPE);
-                setLimit.invoke(mgr, MAX_ENTITY_EXPANSIONS);
-
-                parser.setProperty(XERCES_SECURITY_MANAGER_PROPERTY, mgr);
-                // Stop once one can be setup without error
-                return;
-            } catch (ClassNotFoundException e) {
-                // continue without log, this is expected in some setups
-            } catch (Throwable e) {
-                // NOSONAR - also catch things like NoClassDefError here
-                // throttle the log somewhat as it can spam the log otherwise
-                if (System.currentTimeMillis() > LAST_LOG + 
TimeUnit.MINUTES.toMillis(5)) {
-                    LOG.warn(
-                            "SAX Security Manager could not be setup [log 
suppressed for 5 " +
-                                    "minutes]",
-                            e);
-                    LAST_LOG = System.currentTimeMillis();
-                }
-            }
-        }
-
-        // separate old version of Xerces not found => use the builtin way of 
setting the property
-        try {
-            
parser.setProperty("http://www.oracle.com/xml/jaxp/properties/entityExpansionLimit";,
-                    MAX_ENTITY_EXPANSIONS);
-        } catch (SAXException e) {     // NOSONAR - also catch things like 
NoClassDefError here
-            // throttle the log somewhat as it can spam the log otherwise
-            if (System.currentTimeMillis() > LAST_LOG + 
TimeUnit.MINUTES.toMillis(5)) {
-                LOG.warn("SAX Security Manager could not be setup [log 
suppressed for 5 minutes]",
-                        e);
-                LAST_LOG = System.currentTimeMillis();
-            }
-        }
-    }
-
-    private static void trySetStaxSecurityManager(XMLInputFactory 
inputFactory) {
-        //try default java entity expansion, then fallback to woodstox, then 
warn...once.
-        try {
-            
inputFactory.setProperty("http://www.oracle.com/xml/jaxp/properties/entityExpansionLimit";,
-                    MAX_ENTITY_EXPANSIONS);
-        } catch (IllegalArgumentException e) {
-            try {
-                inputFactory.setProperty("com.ctc.wstx.maxEntityCount", 
MAX_ENTITY_EXPANSIONS);
-            } catch (IllegalArgumentException e2) {
-                if (HAS_WARNED_STAX.getAndSet(true) == false) {
-                    LOG.warn("Could not set limit on maximum entity expansions 
for: " + inputFactory.getClass());
-                }
-            }
-
-        }
-    }
-
     /**
      * Get the maximum number of times a SAXParser or DOMBuilder may be reused.
      *
@@ -858,7 +728,7 @@ public class XMLReaderUtils implements Serializable {
     /**
      * Set the pool size for cached XML parsers.  This has a side
      * effect of locking the pool, and rebuilding the pool from
-     * scratch with the most recent settings, such as {@link 
#MAX_ENTITY_EXPANSIONS}
+     * scratch with the most recent settings.
      *
      * As of Tika 3.2.1, if a value of <code>0</code> is passed in, no 
SAXParsers or DOMBuilders
      * will be pooled, and a new parser/builder will be built for each parse.
@@ -917,26 +787,28 @@ public class XMLReaderUtils implements Serializable {
         POOL_SIZE = poolSize;
     }
 
+    /**
+     * @return -1: Tika sets no entity expansion limit; the JAXP provider's
+     * secure-processing limits apply
+     * @deprecated since 4.2.0, removal planned for 5.0
+     */
+    @Deprecated
     public static int getMaxEntityExpansions() {
-        return MAX_ENTITY_EXPANSIONS;
+        return -1;
     }
 
     /**
-     * Set the maximum number of entity expansions allowable in SAX/DOM/StAX 
parsing.
-     * <b>NOTE:</b>A value less than or equal to zero indicates no limit.
-     * This will override the system property {@link 
#JAXP_ENTITY_EXPANSION_LIMIT_KEY}
-     * and the {@link #DEFAULT_MAX_ENTITY_EXPANSIONS} value for allowable 
entity expansions
-     * <p>
-     * <b>NOTE:</b> To trigger a rebuild of the pool of parsers with this 
setting,
-     * the client must call {@link #setPoolSize(int)} to rebuild the SAX and 
DOM parsers
-     * with this setting.
-     * </p>
+     * No-op. Tika no longer sets an entity expansion limit; the JAXP 
provider's
+     * secure-processing limits apply on every parse.
      *
-     * @param maxEntityExpansions -- maximum number of allowable entity 
expansions
-     * @since Apache Tika 1.19
+     * @deprecated since 4.2.0, removal planned for 5.0
      */
+    @Deprecated
     public static void setMaxEntityExpansions(int maxEntityExpansions) {
-        MAX_ENTITY_EXPANSIONS = maxEntityExpansions;
+        if (!HAS_WARNED_ENTITY_LIMIT.getAndSet(true)) {
+            LOG.warn("setMaxEntityExpansions is ignored since 4.2.0; " +
+                    "the JAXP provider's secure-processing limits apply");
+        }
     }
 
     /**
@@ -954,66 +826,12 @@ public class XMLReaderUtils implements Serializable {
     }
 
     private static PoolSAXParser buildPoolParser(int generation, SAXParser 
parser) {
-        boolean canReset = false;
         try {
             parser.reset();
-            canReset = true;
-        } catch (UnsupportedOperationException e) {
-            canReset = false;
-        }
-        boolean hasSecurityManager = false;
-        try {
-            Object mgr =
-                    
Class.forName(XERCES_SECURITY_MANAGER).getDeclaredConstructor().newInstance();
-            Method setLimit = 
mgr.getClass().getMethod("setEntityExpansionLimit", Integer.TYPE);
-            setLimit.invoke(mgr, MAX_ENTITY_EXPANSIONS);
-
-            parser.setProperty(XERCES_SECURITY_MANAGER_PROPERTY, mgr);
-            hasSecurityManager = true;
-        } catch (SecurityException e) {
-            //don't swallow security exceptions
-            throw e;
-        } catch (ClassNotFoundException e) {
-            // continue without log, this is expected in some setups
-        } catch (Throwable e) {
-            // NOSONAR - also catch things like NoClassDefError here
-            // throttle the log somewhat as it can spam the log otherwise
-            if (System.currentTimeMillis() > LAST_LOG + 
TimeUnit.MINUTES.toMillis(5)) {
-                LOG.warn("SAX Security Manager could not be setup [log 
suppressed for 5 minutes]",
-                        e);
-                LAST_LOG = System.currentTimeMillis();
-            }
-        }
-
-        boolean canSetJaxPEntity = false;
-        if (!hasSecurityManager) {
-            // use the builtin way of setting the property
-            try {
-                
parser.setProperty("http://www.oracle.com/xml/jaxp/properties/entityExpansionLimit";,
-                        MAX_ENTITY_EXPANSIONS);
-                canSetJaxPEntity = true;
-            } catch (SAXException e) {     // NOSONAR - also catch things like 
NoClassDefError here
-                // throttle the log somewhat as it can spam the log otherwise
-                if (System.currentTimeMillis() > LAST_LOG + 
TimeUnit.MINUTES.toMillis(5)) {
-                    LOG.warn(
-                            "SAX Security Manager could not be setup [log 
suppressed for 5 " +
-                                    "minutes]",
-                            e);
-                    LAST_LOG = System.currentTimeMillis();
-                }
-            }
-        }
-
-        if (!canReset && hasSecurityManager) {
-            return new XercesPoolSAXParser(generation, parser);
-        } else if (canReset && hasSecurityManager) {
-            return new Xerces2PoolSAXParser(generation, parser);
-        } else if (canReset && !hasSecurityManager && canSetJaxPEntity) {
             return new BuiltInPoolSAXParser(generation, parser);
-        } else {
+        } catch (UnsupportedOperationException e) {
             return new UnrecognizedPoolSAXParser(generation, parser);
         }
-
     }
 
     private static void clearReader(XMLReader reader) {
@@ -1080,46 +898,6 @@ public class XMLReaderUtils implements Serializable {
 
     }
 
-    private static class XercesPoolSAXParser extends PoolSAXParser {
-        public XercesPoolSAXParser(int generation, SAXParser parser) {
-            super(generation, parser);
-        }
-
-        @Override
-        public void reset() {
-            //don't do anything
-            try {
-                XMLReader reader = saxParser.getXMLReader();
-                clearReader(reader);
-            } catch (SAXException e) {
-                //swallow
-            }
-        }
-    }
-
-    private static class Xerces2PoolSAXParser extends PoolSAXParser {
-        public Xerces2PoolSAXParser(int generation, SAXParser parser) {
-            super(generation, parser);
-        }
-
-        @Override
-        void reset() {
-            try {
-                Object object = 
saxParser.getProperty(XERCES_SECURITY_MANAGER_PROPERTY);
-                saxParser.reset();
-                saxParser.setProperty(XERCES_SECURITY_MANAGER_PROPERTY, 
object);
-            } catch (SAXException e) {
-                LOG.warn("problem resetting sax parser", e);
-            }
-            try {
-                XMLReader reader = saxParser.getXMLReader();
-                clearReader(reader);
-            } catch (SAXException e) {
-                // ignored
-            }
-        }
-    }
-
     private static class BuiltInPoolSAXParser extends PoolSAXParser {
         public BuiltInPoolSAXParser(int generation, SAXParser parser) {
             super(generation, parser);
@@ -1137,9 +915,8 @@ public class XMLReaderUtils implements Serializable {
         }
     }
 
+    //parser that does not support reset(); try anyway on every release
     private static class UnrecognizedPoolSAXParser extends PoolSAXParser {
-        //if unrecognized, try to set all protections
-        //and try to reset every time
         public UnrecognizedPoolSAXParser(int generation, SAXParser parser) {
             super(generation, parser);
         }
@@ -1157,7 +934,6 @@ public class XMLReaderUtils implements Serializable {
             } catch (SAXException e) {
                 // ignored
             }
-            trySetXercesSecurityManager(saxParser);
         }
     }
 
diff --git 
a/tika-core/src/test/java/org/apache/tika/utils/XMLReaderUtilsTest.java 
b/tika-core/src/test/java/org/apache/tika/utils/XMLReaderUtilsTest.java
index 3a70f0aefc..d7c30d8557 100644
--- a/tika-core/src/test/java/org/apache/tika/utils/XMLReaderUtilsTest.java
+++ b/tika-core/src/test/java/org/apache/tika/utils/XMLReaderUtilsTest.java
@@ -51,6 +51,7 @@ import org.w3c.dom.Document;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
 import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
 
 import org.apache.tika.parser.ParseContext;
 import org.apache.tika.sax.ToTextContentHandler;
@@ -111,6 +112,9 @@ public class XMLReaderUtilsTest {
     private static final String[] EXTERNAL_ENTITY_XMLS = new String[]{ 
EXTERNAL_DTD_SIMPLE_FILE, EXTERNAL_DTD_SIMPLE_URL,
             EXTERNAL_ENTITY, EXTERNAL_LOCAL_DTD };
 
+    //above the entity expansion limit Tika set through 4.1.0
+    private static final int EXTERNAL_REFERENCES = 25;
+
     private static final String[] BILLION_LAUGHS = new String[]{ 
BILLION_LAUGHS_CLASSICAL, BILLION_LAUGHS_VARIANT };
 
     @AfterAll
@@ -390,6 +394,35 @@ public class XMLReaderUtilsTest {
         assertEquals("beforeALLOWED_CONTENTafter", output.toString());
     }
 
+    @ParameterizedTest
+    @ValueSource(booleans = {false, true})
+    public void testManyExternalReferencesParse(boolean dom, @TempDir Path 
dir) throws Exception {
+        // external references resolve to nothing and must not fail the parse; 
nothing is read
+        Path external = dir.resolve("external.dtd");
+        Files.writeString(external, "<!ENTITY ext 'LEAKED'>");
+        StringBuilder sb = new StringBuilder("<!DOCTYPE root SYSTEM '" + 
external.toUri() +
+                "' [<!ENTITY ext SYSTEM '" + external.toUri() + "'>]><root>");
+        for (int i = 0; i < EXTERNAL_REFERENCES; i++) {
+            sb.append("<e>a&ext;b</e>");
+        }
+        String xml = sb.append("</root>").toString();
+        String text;
+        if (dom) {
+            Document doc = XMLReaderUtils.buildDOM(new StringReader(xml), new 
ParseContext());
+            text = doc.getDocumentElement().getTextContent();
+        } else {
+            StringBuilder chars = new StringBuilder();
+            XMLReaderUtils.parseSAX(new StringReader(xml), new 
DefaultHandler() {
+                @Override
+                public void characters(char[] ch, int start, int length) {
+                    chars.append(ch, start, length);
+                }
+            }, new ParseContext());
+            text = chars.toString();
+        }
+        assertEquals("ab".repeat(EXTERNAL_REFERENCES), text);
+    }
+
     private void limitCheck(SAXException e) throws SAXException {
         String msg = e.getLocalizedMessage();
         if (msg == null) {
diff --git 
a/tika-serialization/src/main/java/org/apache/tika/config/loader/TikaLoader.java
 
b/tika-serialization/src/main/java/org/apache/tika/config/loader/TikaLoader.java
index 707a96ae5f..4e96125080 100644
--- 
a/tika-serialization/src/main/java/org/apache/tika/config/loader/TikaLoader.java
+++ 
b/tika-serialization/src/main/java/org/apache/tika/config/loader/TikaLoader.java
@@ -582,7 +582,6 @@ public class TikaLoader {
      *     "maxNumberLength": 500
      *   },
      *   "xml-reader-utils": {
-     *     "maxEntityExpansions": 1000,
      *     "maxNumReuses": 100,
      *     "poolSize": 10
      *   }
@@ -610,6 +609,10 @@ public class TikaLoader {
             GlobalSettings.XmlReaderUtilsConfig xmlReaderUtilsConfig =
                     config.deserialize("xml-reader-utils", 
GlobalSettings.XmlReaderUtilsConfig.class);
             if (xmlReaderUtilsConfig != null) {
+                if (xmlReaderUtilsConfig.getMaxEntityExpansions() != null) {
+                    LOG.warn("xml-reader-utils.maxEntityExpansions is ignored 
since 4.2.0; " +
+                            "the JAXP provider's secure-processing limits 
apply");
+                }
                 globalSettings.setXmlReaderUtils(xmlReaderUtilsConfig);
             }
         }
diff --git 
a/tika-serialization/src/main/java/org/apache/tika/serialization/config/GlobalSettings.java
 
b/tika-serialization/src/main/java/org/apache/tika/serialization/config/GlobalSettings.java
index 3100cf87e6..a7da03a923 100644
--- 
a/tika-serialization/src/main/java/org/apache/tika/serialization/config/GlobalSettings.java
+++ 
b/tika-serialization/src/main/java/org/apache/tika/serialization/config/GlobalSettings.java
@@ -26,7 +26,6 @@ import com.fasterxml.jackson.annotation.JsonProperty;
  * <pre>
  * {
  *   "xml-reader-utils": {
- *     "maxEntityExpansions": 1000,
  *     "maxNumReuses": 100,
  *     "poolSize": 10
  *   }
@@ -74,8 +73,11 @@ public class GlobalSettings {
      */
     public static class XmlReaderUtilsConfig {
         /**
-         * Maximum entity expansions allowed in XML parsing.
+         * Ignored since 4.2.0: the JAXP provider's secure-processing limits 
apply.
+         *
+         * @deprecated since 4.2.0, removal planned for 5.0
          */
+        @Deprecated
         @JsonProperty("maxEntityExpansions")
         private Integer maxEntityExpansions;
 

Reply via email to