Skip to content

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.

Updated 02 Nov 2026Checked against cli@de9b52a
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), XMLInputFactory setProperty(SUPPORT_DTD, true) / "javax.xml.stream.supportDTD", and setAttribute/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) and ProhibitDtd = false.
  • Python: lxml XMLParser(load_dtd=True), XMLParser(dtd_validation=True) and XMLParser(attribute_defaults=True), including arguments on later lines.
  • PHP: LIBXML_DTDLOAD, LIBXML_DTDATTR, LIBXML_DTDVALID, $dom->resolveExternals = true, libxml_disable_entity_loader(false) and XMLReader::setParserProperty(XMLReader::LOADDTD|VALIDATE|DEFAULTATTRS, true).
  • Ruby: Nokogiri config.dtdload / config.dtdvalid and ParseOptions::DTDLOAD / DTDVALID / DTDATTR; libxml-ruby Parser::Options::DTDLOAD and XML.default_load_external_dtd = true. The dtdload? 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

  1. Leave DTD processing disabled: disallow-doctype-decl true, SUPPORT_DTD false, DtdProcessing.Prohibit, load_dtd=False, no LIBXML_DTD* flags.
  2. If a DTD is genuinely required, validate against a local, trusted DTD with network access and external entities disabled.

References

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.

Edit this pageSources: cli/internal/sast/rules/vnx-827.rego, cli/internal/sast/docs/vnx-827.md
esc
↑ ↓ move↵ openSearches in your browser. A key like autonomy.max or a code like threshold_required jumps straight to it.