This is an automated email from the ASF dual-hosted git repository.
garydgregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-digester.git
The following commit(s) were added to refs/heads/master by this push:
new 1f8a73d9 Harden XML parsing via commons-secure-xml (#289)
1f8a73d9 is described below
commit 1f8a73d99f931f3d9a7a1ab5b9cc2e4fa8c6c132
Author: Piotr P. Karwasz <[email protected]>
AuthorDate: Sun Sep 6 14:55:54 2026 +0200
Harden XML parsing via commons-secure-xml (#289)
* Harden XML parsing via commons-secure-xml
Create SAX parser and document builder factories through
org.apache.commons:commons-secure-xml. The secure factories enable
FEATURE_SECURE_PROCESSING and install a non-removable entity-resolver
floor on every parser they produce: external DTD, entity, schema and
XInclude lookups that a caller-set resolver does not resolve are
resolved to empty content instead of being fetched, and internal entity
expansion is bounded, regardless of the JAXP implementation on the
classpath.
Changes:
- Add the commons-secure-xml dependency (1.0.0-SNAPSHOT until its first
release) to commons-digester3-core.
- Route factory creation through SecureSAXParserFactory in
Digester.getFactory() and DigesterLoader, and through
SecureDocumentBuilderFactory in NodeCreateRule. The caller-facing
configuration (namespace and XInclude awareness, validation, schema,
features and properties) keeps working, and getFactory() still
returns a plain SAXParserFactory.
- Digester itself acts as the entity resolver of the readers it
creates, and resolvers installed by the caller keep precedence over
the floor, so registered entities, relative DTDs and DTD validation
resolve exactly as before; the floor only takes effect for parsers
whose resolver chain leaves a lookup unresolved.
- Callers supplying their own SAXParser or XMLReader (constructors and
DigesterLoader.newDigester overloads) keep full control of their
parser configuration.
- Run the CI and CodeQL builds with -Puse-apache-snapshots (inherited
from the org.apache:apache parent POM) so the commons-secure-xml
SNAPSHOT resolves; CodeQL's autobuild receives the profile through
MAVEN_ARGS.
Assisted-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01MHgnMnGWHQoH2zD2jFdoMT
* Use the Commons Secure XML 1.0.0 release candidate
Bump org.apache.commons:commons-secure-xml from 1.0.0-SNAPSHOT to 1.0.0
and add the temporary staging repository
https://repository.apache.org/content/repositories/orgapachecommons-1962/
after Central, so the vote gets downstream CI results. Drop the
-Puse-apache-snapshots profile from the CI workflows, which the release
version no longer needs. Remove the staging repository once 1.0.0 is
released.
Assisted-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_0167e29ScPEdfzJnEFm95imK
* Bump Apache Commons Secure XML from 1.0.0-SNAPSHOT to 1.0.0
---------
Co-authored-by: Gary Gregory <[email protected]>
---
commons-digester3-core/pom.xml | 5 +++++
.../src/main/java/org/apache/commons/digester3/Digester.java | 3 ++-
.../src/main/java/org/apache/commons/digester3/NodeCreateRule.java | 3 ++-
.../java/org/apache/commons/digester3/binder/DigesterLoader.java | 3 ++-
src/changes/changes.xml | 3 +++
5 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/commons-digester3-core/pom.xml b/commons-digester3-core/pom.xml
index 763cd337..d04cf94f 100644
--- a/commons-digester3-core/pom.xml
+++ b/commons-digester3-core/pom.xml
@@ -34,6 +34,11 @@
<name>Apache Commons Digester :: Core</name>
<dependencies>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-secure-xml</artifactId>
+ <version>1.0.0</version>
+ </dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
diff --git
a/commons-digester3-core/src/main/java/org/apache/commons/digester3/Digester.java
b/commons-digester3-core/src/main/java/org/apache/commons/digester3/Digester.java
index 5aa17f36..dc8a7781 100644
---
a/commons-digester3-core/src/main/java/org/apache/commons/digester3/Digester.java
+++
b/commons-digester3-core/src/main/java/org/apache/commons/digester3/Digester.java
@@ -48,6 +48,7 @@ import javax.xml.validation.Schema;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.commons.xml.secure.SecureSAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.EntityResolver;
@@ -1589,7 +1590,7 @@ public class Digester
{
if ( factory == null )
{
- factory = SAXParserFactory.newInstance();
+ factory = SecureSAXParserFactory.newInstance();
factory.setNamespaceAware( namespaceAware );
factory.setXIncludeAware( xincludeAware );
factory.setValidating( validating );
diff --git
a/commons-digester3-core/src/main/java/org/apache/commons/digester3/NodeCreateRule.java
b/commons-digester3-core/src/main/java/org/apache/commons/digester3/NodeCreateRule.java
index 87bd7ef2..7882fab4 100644
---
a/commons-digester3-core/src/main/java/org/apache/commons/digester3/NodeCreateRule.java
+++
b/commons-digester3-core/src/main/java/org/apache/commons/digester3/NodeCreateRule.java
@@ -23,6 +23,7 @@ import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
+import org.apache.commons.xml.secure.SecureDocumentBuilderFactory;
import org.w3c.dom.Attr;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
@@ -335,7 +336,7 @@ public class NodeCreateRule
public NodeCreateRule( final int nodeType )
throws ParserConfigurationException
{
- this( nodeType,
DocumentBuilderFactory.newInstance().newDocumentBuilder() );
+ this( nodeType,
SecureDocumentBuilderFactory.newInstance().newDocumentBuilder() );
}
/**
diff --git
a/commons-digester3-core/src/main/java/org/apache/commons/digester3/binder/DigesterLoader.java
b/commons-digester3-core/src/main/java/org/apache/commons/digester3/binder/DigesterLoader.java
index 0fa0c206..8cf5cd20 100644
---
a/commons-digester3-core/src/main/java/org/apache/commons/digester3/binder/DigesterLoader.java
+++
b/commons-digester3-core/src/main/java/org/apache/commons/digester3/binder/DigesterLoader.java
@@ -43,6 +43,7 @@ import org.apache.commons.digester3.Rules;
import org.apache.commons.digester3.RulesBase;
import org.apache.commons.digester3.StackAction;
import org.apache.commons.digester3.Substitutor;
+import org.apache.commons.xml.secure.SecureSAXParserFactory;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.Locator;
@@ -107,7 +108,7 @@ public final class DigesterLoader
/**
* The SAXParserFactory to create new default {@link Digester} instances.
*/
- private final SAXParserFactory factory = SAXParserFactory.newInstance();
+ private final SAXParserFactory factory =
SecureSAXParserFactory.newInstance();
private final Iterable<RulesModule> rulesModules;
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 241d9c42..645b96cc 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -27,6 +27,9 @@
<action dev="simonetripodi" type="add" issue="DIGESTER-171" due-to="Nick
Williams, Ivan Diana">Add DefaultThrowingErrorHandler to Digester API.</action>
<action dev="ggregory" type="add" due-to="Gary Gregory">Add Maven property
project.build.outputTimestamp for build reproducibility.</action>
<!-- FIX -->
+ <action dev="pkarwasz" type="fix" due-to="Piotr P. Karwasz, Gary Gregory">
+ Create SAX parser and document builder factories through
org.apache.commons:commons-secure-xml, which bounds entity expansion and
enables XML secure processing.
+ </action>
<action dev="simonetripodi" type="fix" issue="DIGESTER-175">
Regression: DigesterTestCase#testPopNamedStackNotPushed expects
EmptyStackException.
</action>