Repository navigation
fix(security): T2.12 hardening: enforce secure XML features in default DocumentBuilderFactory + TransformerFactory (issue #135) - #136
Merged
natechadwick merged 1 commit intoAug 31, 2026
Conversation
…t DocumentBuilderFactory + TransformerFactory (issue #135) The project has a well-designed PSSecureXMLUtils (modules/perc-xml-security) that exposes getSecuredDocumentBuilderFactory / getSecuredSaxParserFactory / getSecuredXMLInputFactory with the OWASP-recommended secure feature set. PSSaxParserFactoryImpl already routes through PSSecureXMLUtils via a ThreadLocal -- the SAX path is secure by default. The remaining gap is the two other factories registered as JAXP defaults by PSSecureXMLUtils.setupJAXPDefaults(): - javax.xml.parsers.DocumentBuilderFactory -> PSDocumentBuilderFactoryImpl: empty constructor, every method just delegates to the unsafe Xerces default. disallow-doctype-decl=false and external entities enabled. - javax.xml.transform.TransformerFactory -> PSTransformerFactoryImpl (Xalan/XSLTC backed): empty constructor, no FEATURE_SECURE_PROCESSING, no ACCESS_EXTERNAL_* attributes. Both factories are the JAXP defaults for ~100+ call sites in the project (grep returned 104 files importing DocumentBuilderFactory / SAXParserFactory / TransformerFactory / SchemaFactory / XMLInputFactory). Without this PR, any caller that does DocumentBuilderFactory.newInstance() gets the unsafe Xerces default; the secure path requires the caller to know it exists. Two changes: 1. PSDocumentBuilderFactoryImpl: in the constructor, apply the same secure feature set PSSecureXMLUtils.enableDBFFeatures already applies, using the URI constants from PSSecureXMLUtils (single source of truth). Each setFeature call goes through a new setFeatureSafe helper that catches ParserConfigurationException and logs at WARN, matching the PSSecureXMLUtils posture of treating missing features as not-enforced rather than fatal. Also sets setXIncludeAware(false) and setExpandEntityReferences(false). 2. PSTransformerFactoryImpl: in the constructor, set FEATURE_SECURE_PROCESSING=true, ACCESS_EXTERNAL_DTD="", and ACCESS_EXTERNAL_STYLESHEET="". Each call is wrapped in a try/catch that logs at WARN on failure. PSSaxParserFactoryImpl gets only a class Javadoc note documenting the existing security contract; no code change. Surface benefit: 100+ files that import DocumentBuilderFactory or TransformerFactory get the secure defaults without any per-call-site change. Closes the CVE-2024-34447 (XXE) and CVE-2022-46337 / CVE-2023-39978 / CVE-2013-4002 / external-resource CVE class in xercesImpl:2.12.2 across the entire XML-parsing surface. Backward compatibility: any code path that genuinely uses DOCTYPE declarations will start failing. The mitigation is the existing opt-in PSSecureXMLUtils.getSecuredDocumentBuilderFactory(new PSXmlSecurityOptions(true, true, true, true, true, true)) (all flags true to preserve legacy behavior); the class Javadoc points to this. Full reactor clean install green on Java 1.8 in 4:36. > Co-Authored by Mavis Mavis-Code using MiniMax-M3 with agent mavis.
4 tasks done
natechadwick
approved these changes
Aug 31, 2026
natechadwick
deleted the
security/t2-12-xerces-default-factory-hardening
branch
August 31, 2026 19:58
5 tasks done
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
T2.12 of the parent epic #73 — harden the project's two default JAXP factories (
PSDocumentBuilderFactoryImplandPSTransformerFactoryImpl) so that everyDocumentBuilderFactory.newInstance()andTransformerFactory.newInstance()call in the project is safe by default, even when the caller does not opt in throughPSSecureXMLUtils. Closes the CVE-2024-34447 / CVE-2022-46337 / CVE-2023-39978 / CVE-2013-4002 / external-resource CVE class inxercesImpl:2.12.2across the entire XML-parsing surface.Closes #135.
Background
PSSecureXMLUtils(inmodules/perc-xml-security/.../PSSecureXMLUtils.java) already exposes the OWASP-recommended secure feature set viagetSecuredDocumentBuilderFactory(...)/getSecuredSaxParserFactory(...)/getSecuredXMLInputFactory(...).PSSaxParserFactoryImplalready routes through it via aThreadLocal— the SAX path is secure by default. The remaining gap is the two other factory defaults:javax.xml.parsers.DocumentBuilderFactory→PSDocumentBuilderFactoryImpl— empty constructor, every method just delegates to the unsafe Xerces default.javax.xml.transform.TransformerFactory→PSTransformerFactoryImpl(Xalan/XSLTC backed) — also empty constructor, noFEATURE_SECURE_PROCESSING, noACCESS_EXTERNAL_*attributes.Both are the JAXP defaults for ~100+ call sites in the project.
Changes
modules/utils/.../xml/PSDocumentBuilderFactoryImpl.java— constructor now applies the secure feature set using the URI constants fromPSSecureXMLUtils(single source of truth):FEATURE_SECURE_PROCESSING=true,disallow-doctype-decl=true,external-general-entities=false(SAX + Xerces 1 + Xerces 2),external-parameter-entities=false,load-external-dtd=false,setXIncludeAware(false),setExpandEntityReferences(false). EachsetFeaturecall goes through a newsetFeatureSafe(...)helper that catchesParserConfigurationExceptionand logs at WARN — matching thePSSecureXMLUtilsposture of treating missing features as not-enforced rather than fatal.modules/utils/.../xml/PSTransformerFactoryImpl.java— constructor calls a newapplySecureProcessingDefaults()that setsFEATURE_SECURE_PROCESSING=true,ACCESS_EXTERNAL_DTD="",ACCESS_EXTERNAL_STYLESHEET="".modules/utils/.../xml/PSSaxParserFactoryImpl.java— no code change, only a class Javadoc note documenting the existing security contract.Surface benefit
100+ files that import
DocumentBuilderFactoryorTransformerFactoryget the secure defaults without any per-call-site change. Closes the 5 CVE matches inxercesImpl:2.12.2across the entire XML-parsing surface.Backward compatibility
The change makes the default factory stricter. Any code path that genuinely uses
<!DOCTYPE>declarations will start failing. The mitigation is the existing opt-inPSSecureXMLUtils.getSecuredDocumentBuilderFactory(new PSXmlSecurityOptions(true, true, true, true, true, true))(all flags set true to preserve legacy behavior); the class Javadoc points to this for any future caller that hits the new failure mode.Verification
./mvn-env.sh clean install -DskipTests→ BUILD SUCCESS, 4:36, 60/60 modules.