VNX-827: Improper Control of Document Type Definition
Reports XML parser settings that explicitly turn on DOCTYPE/DTD processing in Java, C#, Python (lxml), PHP (libxml, XMLReader) and Ruby (Nokogiri, libxml-ruby), letting a document declare its own entities or pull an external DTD.
| Field | Value |
|---|---|
| Rule ID | VNX-827 |
| Severity | Medium |
| SARIF level | warning |
| Kind | sast |
| Languages | Java, C#, Python, PHP, Ruby |
| CWE | CWE-827 |
| CAPEC | CAPEC-66 |
| ATT&CK | T1190 |
| CWSS vector | CWSS:1.0/TI:M/AP:A/AL:A/IC:N/FC:LT/RP:N/RL:A/AV:I/AS:N/IN:A/SC:A/BI:M/DI:H/EX:M/EC:N/P:C |
| Tags | improper-control-of-document-type-definition cwe-827 xml dtd xxe |
| Source | internal/sast/rules/vnx-827.rego |
Overview
VNX-827 maps to CWE-827: Improper Control of Document Type Definition. It reports configuration that explicitly enables DTD processing:
- Java:
setFeature("http://apache.org/xml/features/disallow-doctype-decl", false)(or a constant whose name says DOCTYPE),setFeature(load-external-dtd, true),XMLInputFactorysetProperty(SUPPORT_DTD, true)/"javax.xml.stream.supportDTD", andsetAttribute/setProperty(ACCESS_EXTERNAL_DTD, "all")or a protocol list, including calls whose arguments continue on the next lines. - C#:
DtdProcessing = DtdProcessing.Parse(assignment or object initialiser) andProhibitDtd = false. - Python: lxml
XMLParser(load_dtd=True),XMLParser(dtd_validation=True)andXMLParser(attribute_defaults=True), including arguments on later lines. - PHP:
LIBXML_DTDLOAD,LIBXML_DTDATTR,LIBXML_DTDVALID,$dom->resolveExternals = true,libxml_disable_entity_loader(false)andXMLReader::setParserProperty(XMLReader::LOADDTD|VALIDATE|DEFAULTATTRS, true). - Ruby: Nokogiri
config.dtdload/config.dtdvalidandParseOptions::DTDLOAD/DTDVALID/DTDATTR; libxml-rubyParser::Options::DTDLOADandXML.default_load_external_dtd = true. Thedtdload?predicates are not reported.
Not reported: the same settings switched off (disallow-doctype-decl true, SUPPORT_DTD false, ACCESS_EXTERNAL_DTD "", DtdProcessing.Prohibit/Ignore, load_dtd=False, nodtdload), comparisons, unrelated features, factories left at their defaults (VNX-JAVA-004 and VNX-JAVA-029 judge unhardened Java factories), comments and string literals.
Why This Matters
A document that may declare a DTD can define nested entities that expand exponentially (Billion Laughs) or reference an external DTD and parameter entities that read local files and send them out (XXE). Turning DTDs on hands that control to whoever writes the document.
What Gets Flagged
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", false); // FLAGGED
xif.setProperty(XMLInputFactory.SUPPORT_DTD, true); // FLAGGED
settings.DtdProcessing = DtdProcessing.Parse; // FLAGGED
parser = etree.XMLParser(load_dtd=True) # FLAGGED
Remediation
- Leave DTD processing disabled:
disallow-doctype-decltrue,SUPPORT_DTDfalse,DtdProcessing.Prohibit,load_dtd=False, noLIBXML_DTD*flags. - If a DTD is genuinely required, validate against a local, trusted DTD with network access and external entities disabled.
References
- CWE-827: Improper Control of Document Type Definition
- OWASP XML External Entity Prevention Cheat Sheet
Suppressing this rule
Put a nosec comment on the line, or on line 1 to cover the whole file. Use the comment marker of the file’s language (#, //, -- or ;):
# nosec vnx-827
// nosec vnx-827
Or record an ignore rule: vulnetix ignore add --rule vnx-827 --reason "...". See Suppressing findings.