External DTD Resolution Failure in JAXP Parsers Within Isolated Build Environments
26.5K reputation · 24 Jul 2021, 07:29 UTC
When an XML document references an external DTD or external entity, a JAXP parser configured to block external entity resolution raises a fatal error. The precise component is the feature controlling external-general-entities on DocumentBuilderFactory or SAXParserFactory. In a repeatable development environment, this creates a conflict: network-dependent DTD resolution makes builds non-deterministic, yet disabling DTD processing rejects valid legacy XML that relies on DTD-defined entities or attribute defaults.
The unresolved decision is whether to disable DTD processing entirely for security and determinism, or keep DTD support and map external identifiers to local files with an XML Catalog. XML Catalogs provide a standard indirection layer that rewrites public and system identifiers to local resources without changing the XML. However, catalog support and resolver APIs differ between JAXP versions and third-party parsers, and secure-processing defaults have changed across JDK releases.
Specific questions: How should a build choose between these approaches when the XML corpus contains both legacy DTD-dependent documents and untrusted input? What parser version assumptions must be documented to make the choice reproducible? And how can a team confirm that the same document parses identically on a developer machine and in an isolated CI runner?
1 answer
1 question comment
Use comments to ask for clarification. Post a solution as an answer.
2,190 reputation · 24 Jul 2021, 19:14 UTC
To refine the decision between disabling DTDs and using catalogs, it is important to distinguish between the disallow-doctype-decl feature and the load-external-dtd feature. While the former completely rejects any XML containing a DOCTYPE, the latter allows the DOCTYPE to exist but prevents the parser from attempting to fetch the external DTD file.
In isolated build environments, setting http://apache.org/xml/features/nonvalidating/load-external-dtd to false can prevent network timeouts without triggering the fatal errors associated with a total DOCTYPE ban. However, this creates a specific risk: if the XML relies on DTD-defined entities (e.g., &companyName;) for content expansion, the parser will fail to resolve those entities, potentially resulting in empty strings or parsing errors depending on the JAXP implementation version.
For reproducible CI runs, teams should verify that the EntityResolver is not just present, but explicitly tested against a "no-network" profile to ensure the parser is hitting the local classpath rather than falling back to a system-level default resolver.