Skip to content

fix(utils): drop dead Xerces-1/Xerces-2 feature URIs from default DocumentBuilderFactory - #205

Merged
natechadwick merged 1 commit into
mainfrom
bugfix/135-xerces-x1x2-feature-removal
Sep 8, 2026
Merged

fix(utils): drop dead Xerces-1/Xerces-2 feature URIs from default DocumentBuilderFactory#205
natechadwick merged 1 commit into
mainfrom
bugfix/135-xerces-x1x2-feature-removal

Conversation

@natechadwick-intsof

Copy link
Copy Markdown
Collaborator

Summary

Drops two dead setFeatureSafe(...) calls in modules/utils/.../PSDocumentBuilderFactoryImpl.java that targeted the legacy Xerces-1 and Xerces-2 external-entity feature URIs. These URIs are not recognized by Xerces 2.12.x, so every DocumentBuilderFactory instantiation in the project produced two WARN lines on the startup log. The actual security controls (SAX-namespace features + FEATURE_SECURE_PROCESSING) remain in place.

Why

PSDocumentBuilderFactoryImpl was set as the project-wide default DocumentBuilderFactory by the T2.12 hardening PR (#136, issue #135). Its constructor calls setFeature for seven features; two of them target URIs that have been dead for years:

  • http://xerces.apache.org/xerces-j/features.html#external-general-entities (X1, Xerces 1.x)
  • http://xerces.apache.org/xerces2-j/features.html#external-general-entities (X2, early Xerces 2.x)

Modern Xerces 2.12.x consolidated those into the SAX-namespace features (http://xml.org/sax/features/external-general-entities, .../external-parameter-entities) and JAXP's FEATURE_SECURE_PROCESSING. The X1/X2 URIs always throw ParserConfigurationException on 2.12.x.

The setFeatureSafe(...) helper catches the exception and logs at WARN. PSDocumentBuilderFactoryImpl is instantiated ~10 times before the webapp finishes startup, so the log gets ~20 of these lines per cold start:

WARN  [com.percussion.xml.PSDocumentBuilderFactoryImpl] T2.12 hardening:
  could not enforce X1_GENERAL_EXTERNAL_ENTITIES_FEATURE=false on
  DocumentBuilderFactory: Feature '...' is not recognized.

(The same X1/X2 URIs are also set on the opt-in PSSecureXMLUtils.enableDBFFeatures path, but that path catches and logs at DEBUG, so it's silent — only the new default-factory path added by PR #136 was loud.)

What stays

The actual security posture is unchanged. The remaining setFeatureSafe calls in the constructor:

  • XMLConstants.FEATURE_SECURE_PROCESSING=true — JAXP standard secure processing
  • DISALLOW_DOCTYPES_FEATURE=true — no <!DOCTYPE> declarations
  • SAX_GENERAL_EXTERNAL_ENTITIES_FEATURE=false — no external general entities
  • SAX_EXTERNAL_PARAMETER_ENTITIES_FEATURE=false — no external parameter entities
  • LOAD_EXTERNAL_DTD=false — no external DTDs
  • setXIncludeAware(false) / setExpandEntityReferences(false) — no XInclude, no entity expansion

The PSSecureXMLUtils.X1/X2_GENERAL_EXTERNAL_ENTITIES_FEATURE constants are untouched (the opt-in path still uses them with DEBUG logging). Only the default-factory path is changed.

Verification

  • grep -n "X1_GENERAL_EXTERNAL\|X2_GENERAL_EXTERNAL" modules/utils/src/main/java/com/percussion/xml/PSDocumentBuilderFactoryImpl.java returns no matches.
  • grep -n "SAX_GENERAL\|SAX_EXTERNAL" ... confirms the SAX features remain set.
  • After rebuild + redeploy of rxutils-8.1.8-SNAPSHOT.jar, the T2.12 hardening: could not enforce X1/X2_..._ENTITIES_FEATURE lines disappear from jetty/base/logs/server.log. The remaining T2.12 hardening messages (FEATURE_SECURE_PROCESSING, DISALLOW_DOCTYPES, SAX_GENERAL, SAX_EXTERNAL_PARAMETER, LOAD_EXTERNAL_DTD) continue to silently no-op as they did before (Xerces already has those values set, so setFeature is a successful no-op).

Out of scope

  • The other startup WARN, Ignored arg <Arg name="threadpool"> in upstream/etc/jetty.xml, is from the bundled Jetty 9.4.58.v20250814 distribution (modules/perc-jetty vendor) and is not introduced by the T2.12 hardening work.

Refs #135

Co-Authored by Mavis Mavis-Code using MiniMax-M3 with agent mavis.

…umentBuilderFactory

PSDocumentBuilderFactoryImpl (the project-wide default registered via
PSSecureXMLUtils.setupJAXPDefaults) was setting two legacy Xerces feature
URIs -- PSSecureXMLUtils.X1_GENERAL_EXTERNAL_ENTITIES_FEATURE and
X2_GENERAL_EXTERNAL_ENTITIES_FEATURE -- alongside the SAX-namespace
external-entity features and JAXP's FEATURE_SECURE_PROCESSING.

The X1/X2 URIs are not recognized by Xerces 2.12.x. Modern Xerces
consolidated the external-entity controls into the SAX-namespace features
(http://xml.org/sax/features/external-general-entities and
.../external-parameter-entities) and the standard JAXP
FEATURE_SECURE_PROCESSING. The legacy URIs were dead code on every
PSSecureXMLUtils opt-in call site too, but PSSecureXMLUtils catches the
ParserConfigurationException and logs at DEBUG, so it was silent. In the
default factory the catch logs at WARN, so every DocumentBuilderFactory
instantiation in the project produced two WARN lines like:

  WARN  [com.percussion.xml.PSDocumentBuilderFactoryImpl] T2.12 hardening:
  could not enforce X1_GENERAL_EXTERNAL_ENTITIES_FEATURE=false on
  DocumentBuilderFactory: Feature
  'http://xerces.apache.org/xerces-j/features.html#external-general-entities'
  is not recognized.

The startup hits PSDocumentBuilderFactoryImpl ~10 times before the webapp
is fully up, so the log gets ~20 of these lines per cold start.

Removing the X1/X2 setFeatureSafe calls is safe: the SAX features
(SAX_GENERAL_EXTERNAL_ENTITIES_FEATURE=false,
SAX_EXTERNAL_PARAMETER_ENTITIES_FEATURE=false) and FEATURE_SECURE_PROCESSING
remain set in the constructor, and they are what actually disables external
entity resolution on Xerces 2.12.x. disallow-doctype-decl, load-external-dtd,
XIncludeAware, and expandEntityReferences are also still set.

The PSSecureXMLUtils.X1/X2_GENERAL_EXTERNAL_ENTITIES_FEATURE constants
remain in PSSecureXMLUtils (the opt-in path still references them with
DEBUG logging) -- this change only touches the default-factory path that
the T2.12 hardening PR added. The analysis doc has a post-merge revision
note documenting the 3.5.x/2.12.x API surface so the URIs don't get
re-added.

Refs #135

> Co-Authored by Mavis Mavis-Code using MiniMax-M3 with agent mavis.
@natechadwick
natechadwick merged commit 41fba05 into main Sep 8, 2026
3 checks passed
@natechadwick
natechadwick deleted the bugfix/135-xerces-x1x2-feature-removal branch September 8, 2026 16:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants