For untrusted XML, keep DTDs, external resources, entity substitution, XInclude, and relaxed parser limits disabled. Bound the input before parsing, use LIBXML_NONET, reject any document type declaration, and cap the records your application accepts.
Last updated: November 13, 2026.
<?php
function readItemNames(string $xml): array
{
if (strlen($xml) > 1_000_000) {
throw new LengthException('XML input is too large');
}
$previous = libxml_use_internal_errors(true);
$reader = null;
try {
$reader = XMLReader::XML($xml, null, LIBXML_NONET);
$items = [];
while ($reader->read()) {
if ($reader->nodeType === XMLReader::DOC_TYPE) {
throw new UnexpectedValueException('DTD declarations are not allowed');
}
if ($reader->nodeType === XMLReader::ELEMENT && $reader->name === 'item') {
$items[] = $reader->readString();
if (count($items) > 10_000) {
throw new LengthException('Too many item elements');
}
}
}
if (libxml_get_errors() !== []) {
throw new UnexpectedValueException('Invalid XML document');
}
return $items;
} finally {
$reader?->close();
libxml_clear_errors();
libxml_use_internal_errors($previous);
}
}The parser operates on a supplied string rather than an untrusted filename or URL. It does not enable entity substitution, DTD loading, DTD validation, XInclude, or LIBXML_PARSEHUGE.
Keep dangerous features off
The PHP libxml constants reference warns that LIBXML_NOENT, LIBXML_DTDLOAD, and LIBXML_DTDVALID can enable external-entity behavior. LIBXML_PARSEHUGE relaxes parser limits and should be reserved for trusted data. LIBXML_NONET blocks network access but is not permission to enable the other features.
The XMLReader::XML documentation accepts a string and a libxml flags bitmask. Passing content directly keeps the initial resource under application control. Reject DTDs when the business format does not require them.
Apply limits outside the parser too
The OWASP XXE Prevention Cheat Sheet recommends disabling DTDs whenever possible and treating unsupported security settings as a configuration failure. Limit upload size, decompressed size, parsing time, element count, text length, and nesting according to the expected format.
Validate required elements and data types after parsing; well-formed XML is not automatically valid application data. Do not return detailed parser paths or server filenames to the client. Keep the full diagnostics in protected logs, and test external entities, internal entity expansion, deep nesting, oversized text, invalid encoding, and a normal document.