Safeguard
Security Guides•

How do you check XML parsing code for XXE in a review?

Check that XML parsers reject DTDs or disable external entities, per language: Java factories, .NET resolvers, Python defusedxml and PHP libxml flags.

Safeguard Security Team
3 min read

Check that every parser handling untrusted XML rejects DOCTYPE declarations or disables external entities and external DTD loading. The exact setting differs by language and parser, so reviewers need a short per language list. If a secure setting is unsupported, treat that as a failure.

General guidance from OWASP

The OWASP XML External Entity Prevention Cheat Sheet advises disabling DTDs where possible and rejecting DOCTYPE declarations if the parser supports it. If DTDs are required, disable external entity resolution and external DTD loading and limit entity expansion. Keep XInclude off unless explicitly required, and restrict external access in schema validation and XSLT as well as plain parsing. It also says to treat an unsupported security setting as a failure, rather than parsing untrusted XML with partial hardening.

Language checklist

LanguageWhat to check
Javadisallow-doctype-decl set to true on DocumentBuilderFactory and SAXParserFactory. For XMLInputFactory, SUPPORT_DTD and IS_SUPPORTING_EXTERNAL_ENTITIES both false. ACCESS_EXTERNAL properties set to empty strings on TransformerFactory and SchemaFactory
.NETTarget framework version, since versions before 4.5.2 are unsafe by default. XmlResolver null, or DtdProcessing set to Prohibit or Ignore on older frameworks
PythonUntrusted XML goes through defusedxml. Set forbid_dtd where the API offers it. Enforce input and decompressed size limits
PHPFlags LIBXML_NOENT, LIBXML_DTDLOAD or LIBXML_DTDVALID on untrusted XML without blocking external resources

Two Java details from the cheat sheet are easy to miss in review. Setting setExpandEntityReferences to false is not a substitute for blocking external resources. And XMLDecoder should not receive untrusted input.

Steps for a review

  1. Find where XML enters the system: API bodies, file imports, SOAP endpoints, document uploads and configuration parsers.
  2. Find the parser construction. The security settings are set on the factory, not at the parse call.
  3. Compare the settings with the table. If the code relies on defaults, look up the default for that version.
  4. Check schema validation and transformation steps, which are separate from parsing and need their own limits.
  5. Check size limits. The cheat sheet notes the Python standard library xmlrpc module is vulnerable to decompression bombs.
// red flag: factory used with defaults
DocumentBuilderFactory f = DocumentBuilderFactory.newInstance();

// safer: reject DOCTYPE declarations
DocumentBuilderFactory f = DocumentBuilderFactory.newInstance();
f.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);

Other formats built on XML

The OWASP page does not address SVG, DOCX or XLSX. Those formats are XML based, so it is reasonable for a reviewer to ask how the code parses them, but that is an inference and not something the source establishes.

Dependencies matter here

Many XXE issues are fixed by upgrading a parsing library. The cheat sheet itself notes that Python's Expat versions below 2.7.2 may be affected by denial of service issues. Checking library versions belongs in the same review as the settings.

Where Safeguard fits

Safeguard scans dependencies and builds SBOMs, so outdated XML libraries show up in your inventory. Try the free scan at gold.safeguard.sh/scan.

Quick check

Is disabling external entities enough on its own?

It is a core step, but OWASP also advises rejecting DTDs where possible, limiting entity expansion and restricting access in schema and XSLT processing.

What if a parser cannot set the secure option?

OWASP says to treat an unsupported security setting as a failure and not continue with partial hardening.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.