ASVS 5.0 V1.5.1 requires that your application configures XML parsers restrictively and disables unsafe features, above all the resolution of external entities, to prevent XML External Entity (XXE) attacks. This is a Level 1 requirement, which means every application that parses XML should meet it.
Why it matters
XML lets a document declare entities that the parser expands. With a permissive parser, an attacker can define an entity that points at a local file or an internal URL. The parser reads it and returns the content in an error or in the parsed output. The result is file disclosure, server side request forgery against internal services, and in some setups denial of service through entity expansion.
The risk hides in places developers do not think of as XML: SOAP endpoints, SAML responses, SVG uploads, Office documents, RSS importers and configuration uploads.
How to implement it
The safest setting is to refuse DOCTYPE declarations entirely. If you need a DTD, disable external entities and external DTD loading explicitly.
Java, with the standard DOM parser:
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
dbf.setXIncludeAware(false);
dbf.setExpandEntityReferences(false);
DocumentBuilder db = dbf.newDocumentBuilder();
Python: use the defusedxml package instead of the standard library parsers, or configure lxml:
from lxml import etree
parser = etree.XMLParser(
resolve_entities=False,
no_network=True,
load_dtd=False,
dtd_validation=False,
)
tree = etree.fromstring(data, parser)
.NET:
var settings = new XmlReaderSettings {
DtdProcessing = DtdProcessing.Prohibit,
XmlResolver = null
};
using var reader = XmlReader.Create(stream, settings);
Set this in one shared helper, so every call site gets the same safe parser. Check the defaults of every library that parses XML for you, including transitive ones such as SAML and document converters. Keep those libraries patched, because several XXE issues were fixed in parser dependencies rather than in application code.
How to test it
Send a document with an external entity to every endpoint and upload feature that accepts XML:
<?xml version="1.0"?>
<!DOCTYPE r [<!ENTITY x SYSTEM "file:///etc/hostname">]>
<r>&x;</r>
A safe parser rejects the DOCTYPE or leaves the entity unexpanded. If the host name shows up in the response, an error message, or a log, the parser is vulnerable. Repeat with an entity that points at a URL you control and watch for an incoming request, which finds blind cases. Also add a unit test per parser helper so a future refactor cannot quietly turn the feature back on.
Where XXE hides in real systems
Most teams fix the obvious endpoint that takes an XML body and miss the quieter ones. Walk through this list for your own application.
SAML single sign on handles XML from an identity provider, and sometimes from a user's browser. Office files such as docx and xlsx are zip archives full of XML, so any converter, previewer or import feature parses XML. SVG images are XML, which makes avatar and logo upload an entry point. SOAP services, RSS and Atom readers, sitemap importers, and configuration or plugin upload screens all take XML too.
Build tools and background workers count as well. A job that processes uploaded documents overnight can leak files from the worker host, which often has broader network access than the web tier.
Blind and out of band cases
Not every XXE shows the file in the response. In a blind case the parser fetches an attacker URL, and the only evidence is an incoming request on the attacker's server. That is still a server side request forgery primitive, and it can reach cloud metadata addresses and internal admin services. Block outbound traffic from parser hosts you do not need, as a second line of defence.
Entity expansion and size limits
A small document can define entities that expand into gigabytes. Even with external entities off, set a limit on document size and, where the parser supports it, on entity expansion. Most secure processing modes do this for you, which is another reason to switch them on rather than leave defaults.
Common mistakes
- Fixing the main endpoint and forgetting file import, SVG or SAML paths.
- Disabling external entities but leaving DTD loading on.
- Relying on the default of an old library version.
- Catching the parser exception and returning its message, which leaks content.
Try it yourself
Scan your project for vulnerable XML parser versions with the free in-browser dependency scan at https://gold.safeguard.sh/scan, then run a static scan to see parser calls without secure settings.
Click through it at your own pace, or open it full screen.
Quick check
Is a WAF rule that blocks the word ENTITY enough?
No. Encodings and alternative syntax can get around string matching. Fix the parser configuration, and treat filtering as an extra layer at most.
Which setting is the strongest in Java?
Disallowing the DOCTYPE declaration with the disallow-doctype-decl feature, because it removes entities altogether.