Redirecting DTD Lookups with XML EntityResolver
This article explains the role of the XML EntityResolver
interface in redirecting Document Type Definition (DTD) lookups to local
classpath resources. When XML parsers encounter external DTD
declarations, they attempt by default to fetch these definitions over
the network, introducing performance bottlenecks and security
vulnerabilities. Implementing EntityResolver allows
developers to intercept these external requests and provide locally
bundled DTD files instead, ensuring fast, reliable, and offline-capable
XML processing.
The Default Behavior of XML Parsers
When an XML parser processes an XML document with a
<!DOCTYPE> declaration referencing an external SYSTEM
or PUBLIC identifier (often an HTTP or HTTPS URL), the parser defaults
to resolving the URI over the network. This behavior introduces
significant drawbacks:
- Network Latency and Failures: Parsing becomes dependent on internet availability and remote server uptime.
- Security Risks: Fetching external entities can expose applications to XML External Entity (XXE) attacks, Server-Side Request Forgery (SSRF), and denial-of-service conditions.
- Rate Limiting: Remote hosts hosting common DTDs may block or throttle repeated requests originating from the parser.
How EntityResolver Intercepts Lookups
The org.xml.sax.EntityResolver interface provides a
standardized hook into the parsing lifecycle via a single method:
public InputSource resolveEntity(String publicId, String systemId);During parsing, whenever the parser encounters an external entity or
DTD reference, it passes the declared publicId and
systemId to this method before attempting a network
lookup:
- Detection: The parser passes the DTD identifier
(e.g.,
http://example.com/dtds/schema.dtd) toresolveEntity. - Matching: The custom implementation checks the identifier against known DTD names or URIs.
- Local Stream Retrieval: If a match occurs, the
application loads the resource from the application’s classpath using
ClassLoader.getResourceAsStream(). - InputSource Creation: The local
InputStreamis wrapped in anorg.xml.sax.InputSourceand returned to the parser. - Fallback: If the entity is not recognized,
returning
nullinstructs the parser to use its default URI resolution mechanism.
Key Benefits of Classpath Redirection
Using EntityResolver to supply local DTDs provides
several architectural advantages:
- Deterministic Builds and Runtime: Applications remain fully functional in air-gapped, firewalled, or offline production environments.
- High Performance: Reading files directly from local memory or packaged JAR files eliminates the overhead of establishing HTTP connections during XML parsing.
- Centralized Dependency Management: DTD versions can be version-controlled alongside the application codebase, preventing unexpected changes or deprecations from external hosts.