Disable External DTD Resolution in XML Parsers

Disabling external Document Type Definition (DTD) resolution is the primary defense against XML External Entity (XXE) injection and XML-based Denial of Service (Billion Laughs) attacks. This guide outlines the specific configuration properties, flags, and code settings required to safely disable external DTDs across modern XML parsers in Java, .NET, Python, PHP, and Node.js.

Java

Java provides multiple XML processing APIs (DocumentBuilderFactory, SAXParserFactory, XMLInputFactory, and TransformerFactory). Each requires explicit feature flags to disable DTD processing.

DocumentBuilderFactory (DOM)

To completely disallow DTDs:

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);

If inline DTDs are required but external DTD resolution must be blocked:

dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
dbf.setXIncludeAware(false);
dbf.setExpandEntityReferences(false);

SAXParserFactory (SAX)

SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
// Or disable external entities specifically:
spf.setFeature("http://xml.org/sax/features/external-general-entities", false);
spf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
spf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);

XMLInputFactory (StAX)

XMLInputFactory xif = XMLInputFactory.newInstance();
xif.setProperty(XMLInputFactory.SUPPORT_DTD, false);
xif.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);

TransformerFactory / SchemaFactory (JAXP)

Restrict external protocols globally using XMLConstants:

TransformerFactory tf = TransformerFactory.newInstance();
tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
tf.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");

.NET (C#)

In .NET Framework 4.5.2+ and .NET Core / .NET 5+, XmlReader is secure by default. However, when working with XmlReaderSettings or legacy XmlDocument, verify the following properties:

XmlReaderSettings

XmlReaderSettings settings = new XmlReaderSettings();
// Completely prohibit DTDs:
settings.DtdProcessing = DtdProcessing.Prohibit; 

// Alternatively, ignore DTDs and remove the resolver:
settings.DtdProcessing = DtdProcessing.Ignore;
settings.XmlResolver = null;

XmlDocument

XmlDocument doc = new XmlDocument();
doc.XmlResolver = null; // Disables external entity resolution

Python

lxml

When using lxml.etree, configure the parser options to prevent network access and entity expansion:

from lxml import etree

parser = etree.XMLParser(
    resolve_entities=False,
    load_dtd=False,
    no_network=True,
    dtd_validation=False
)
tree = etree.fromstring(xml_data, parser=parser)

Python’s standard xml.etree.ElementTree and minidom do not resolve external entities by default, but they are vulnerable to entity expansion attacks. The safest practice in Python is using the defusedxml package, which overrides parsers to reject external DTDs automatically:

import defusedxml.ElementTree as ET

tree = ET.fromstring(xml_data)

PHP

libxml-based Parsers (DOMDocument, SimpleXML, XMLReader)

In PHP 8.0 and later, external entity loading is disabled by default. For PHP versions prior to 8.0, or to ensure strict compliance:

// Disable entity loading globally (PHP < 8.0)
libxml_disable_entity_loader(true);

// When using DOMDocument, avoid LIBXML_NOENT and LIBXML_DTDLOAD flags:
$dom = new DOMDocument();
$dom->loadXML($xmlString, LIBXML_NONET); // LIBXML_NONET disables network access

Node.js

libxmljs

const libxmljs = require("libxmljs");

const xmlDoc = libxmljs.parseXml(xmlString, {
    noent: false,     // Do not expand external entities
    dtdload: false,   // Do not load external DTDs
    dtdvalid: false,  // Do not validate against DTD
    nonet: true       // Disable network access
});

fast-xml-parser

const { XMLParser } = require("fast-xml-parser");

const parser = new XMLParser({
    processEntities: false // Ignores entity parsing
});
const result = parser.parse(xmlString);