Preventing XXE Attacks in Java: Disable External Entity Expansion in XML Parsers
Learn how to configure Java's XML parsers to block XXE attacks by disabling DTDs and external entity resolution. A practical example, verification steps, limits, and common pitfalls are covered.
29 Jun 2026, 05:56 UTC

Why External Entity Expansion Is Dangerous
XML External Entity (XXE) attacks exploit the ability of an XML parser to resolve entity references that point outside the XML document. A malicious payload can read local files, trigger denial‑of‑service by creating huge in‑memory structures, or even reach internal networks through external DTDs.
Configuring DocumentBuilderFactory for XXE Protection
Java’s DocumentBuilderFactory provides a set of feature flags that, when set correctly, prevent the parser from processing DTDs and external entities. The most important flags are:
http://apache.org/xml/features/disallow-doctype-decl– disallows any DOCTYPE declaration.http://xml.org/sax/features/external-general-entities– blocks external general entities.http://xml.org/sax/features/external-parameter-entities– blocks external parameter entities.XMLConstants.FEATURE_SECURE_PROCESSING– enables a set of security‑related defaults.
When all four are enabled, the parser will throw an exception on any attempt to use a DOCTYPE or external entity.
Step‑by‑Step Example
The following snippet shows how to create a secure DocumentBuilderFactory and parse an XML string. It can be run from a standard Java application (no elevated privileges required).
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
public class SecureXmlParser {
public static DocumentBuilderFactory secureFactory() throws Exception {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
// 1. Disallow DOCTYPE declarations
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
// 2. Disable external general entities
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
// 3. Disable external parameter entities
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
// 4. Enable secure processing
dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
return dbf;
}
public static void main(String[] args) throws Exception {
String xml = "<test>Hello</test>"; // replace with user input
DocumentBuilderFactory factory = secureFactory();
DocumentBuilder builder = factory.newDocumentBuilder();
builder.parse(new java.io.ByteArrayInputStream(xml.getBytes("UTF-8")));
System.out.println("XML parsed successfully.");
}
}
Replace the xml variable with the actual XML payload you receive. The parser will reject any payload containing a DOCTYPE or external entity reference.
Verifying the Configuration
To confirm that the flags are active, you can query them after setting:
boolean doctype = dbf.getFeature("http://apache.org/xml/features/disallow-doctype-decl");
boolean generalEnt = dbf.getFeature("http://xml.org/sax/features/external-general-entities");
boolean paramEnt = dbf.getFeature("http://xml.org/sax/features/external-parameter-entities");
boolean secureProc = dbf.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING);
System.out.printf("doctype=%b, general=%b, param=%b, secure=%b\n", doctype, generalEnt, paramEnt, secureProc);
All values should print true for the disallow-doctype flag, false for the external entity flags, and true for secure processing.
Testing with a Malicious Payload
Run the parser against the following XML to ensure it fails:
<!DOCTYPE test [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<test>&xxe;</test>
The parser should throw an exception such as org.xml.sax.SAXParseException: DOCTYPE is disallowed. If it does not, double‑check that the feature names match the parser’s implementation.
Limitations and When DTDs Are Needed
- Disabling DOCTYPE declarations breaks legitimate XML that relies on external DTDs for validation. If your application must consume such XML, consider a whitelist approach: enable the parser but only allow specific, trusted external DTD URLs.
- Large internal entities (the "Billion Laughs" attack) are still possible if external entities are disabled but internal ones are allowed. The
XMLConstants.FEATURE_SECURE_PROCESSINGflag mitigates this by setting limits on entity expansion, but you may need to tuneXMLConstants.ACCESS_EXTERNAL_DTDorXMLConstants.ACCESS_EXTERNAL_SCHEMAfor stricter control. - Some XML libraries (e.g., older Xerces versions) may ignore these feature IDs. Always consult the specific parser’s documentation.
Common Mistakes to Avoid
- Only disabling one feature: If you set only
disallow-doctype-declbut leave the external entity flags at their defaults, an attacker can still use internal entity tricks. - Using a different parser factory: The same safeguards must be applied to
SAXParserFactory,XPathFactory, or any custom factory you instantiate. - Assuming the flags are enabled by default: they are not; you must explicitly set them.
- Not handling the exception: catch
SAXExceptionand return a safe error message rather than exposing stack traces.
Conclusion
By configuring DocumentBuilderFactory with the four key feature flags, Java applications can effectively block XXE attacks that rely on external entity resolution. Verify the configuration with a known malicious payload, and be aware of the trade‑offs when legitimate DTDs are required. Following these steps ensures that XML parsing remains a safe part of your stack.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.