Blocking XML External Entity (XXE) Attacks by Disabling DTD Loading in Common Parsers
Learn how to stop XML External Entity (XXE) attacks by disabling DTD loading in Java, .NET, Python lxml, and libxml2 parsers, with a concrete Java example and verification steps.
27 Aug 2025, 00:21 UTC

The problem: XML parsers that resolve external entities
When an XML parser processes a document that contains a doctype declaration with an external general or parameter entity, it may resolve that entity by reading a local file or making a network request. An attacker who can supply XML input can use this behavior to read sensitive files (e.g., /etc/passwd), perform server‑side request forgery (SSRF), or cause a denial‑of‑service. This class of vulnerability is known as XML External Entity (XXE).
Thesis: Turning off external entity resolution is a low‑cost, effective mitigation
Most mainstream XML parsers expose a feature or property that disables DTD loading and external entity resolution. Enabling this feature stops the parser from accessing external resources while preserving normal well‑formedness checks. The performance impact is negligible because the parser still validates the XML structure; it merely skips the optional DTD processing step.
Worked example: Java DOM parser
The following snippet shows how to configure a DocumentBuilderFactory to block XXE attacks in Java 8 and later. The code sets two features: the generic secure‑processing flag and the Xerces‑specific disallow‑doctype declaration feature.
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.XMLConstants;
import org.w3c.dom.Document;
import java.io.File;
public class SafeXmlParser {
public static Document parse(File xmlFile) throws Exception {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
// Enable generic secure processing (may be a no‑op on some implementations)
dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
// Xerces‑specific: disallow doctype declarations entirely
dbf.setAttribute("http://apache.org/xml/features/disallow-doctype-decl", true);
// Optional: also disable external DTD loading if the parser supports it
dbf.setAttribute("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
return dbf.newDocumentBuilder().parse(xmlFile);
}
}
If the supplied XML contains an external entity reference such as:
<!DOCTYPE test [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
&xxe;
the parser will throw a SAXParseException (or a subclass) indicating that the doctype declaration is not allowed, and the entity will not be resolved. No file system or network access occurs.
Equivalent settings in other popular parsers
- .NET XmlReader:
XmlReaderSettings settings = new XmlReaderSettings(); settings.DtdProcessing = DtdProcessing.Prohibit; - Python lxml:
from lxml import etree parser = etree.XMLParser(resolve_entities=False, no_network=True) - libxml2 (C):
xmlKeepBlanksDefault(0); xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS; xmlSubstituteEntitiesDefault(0);(or useXML_PARSE_NOENTflag cleared).
Consult the documentation for your specific parser version to locate the exact property name; older releases may lack the secure‑processing flag, in which case upgrading to a maintained release is recommended.
Trade‑off and limitation
Disabling DTD loading prevents the use of legitimate external DTDs or internal entity definitions that rely on external resources. If your application depends on such DTDs (for example, to share common XML fragments across services), you must either host the DTDs locally and enable trusted entity resolution, or migrate to a schema‑based validation approach (XSD, RelaxNG) that does not require external entities. Before applying the lock‑down, audit your XML inputs to confirm that no required external entities exist.
Actionable closing
To verify that the mitigation works, create a test file containing an external entity reference (as shown above) and attempt to parse it with your configured parser. The parser should raise an error and no external file should be read. You can monitor file‑system or network activity during the test to confirm that no outbound request is made. Once verified, apply the same configuration to all XML entry points in your service—REST endpoints, message queues, file upload handlers—and treat any parser that throws a DTD‑related exception as a sign of blocked XXE attempt.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.