highCode Injection

XML External Entity (XXE) Attack

What Is This Vulnerability?

XXE attacks exploit XML parsers that process external entity declarations in untrusted XML input. An attacker can define an external entity that references a local file, an internal URL, or a remote server. When the parser resolves the entity, it includes the referenced content in the output, leading to file disclosure, SSRF, or denial of service.

Why It Happens

Many XML parsers have external entity processing enabled by default. Developers who accept XML input for APIs, configuration files, SOAP services, or document uploads may not realize the parser resolves external entities. Legacy systems and enterprise integrations frequently use XML without disabling these dangerous features.

Example Code

Vulnerableroutes/xml.ts
import { parseStringPromise } from "xml2js";

app.post("/parse-xml", async (req, res) => {
  const result = await parseStringPromise(req.body, {
    explicitArray: false,
  });
  res.json(result);
});
Fixedroutes/xml.ts
import { parseStringPromise } from "xml2js";

app.post("/parse-xml", async (req, res) => {
  const result = await parseStringPromise(req.body, {
    explicitArray: false,
    xmlns: false,
    doctype: undefined,
  });
  res.json(result);
});

// Alternatively, reject XML with DOCTYPE declarations entirely
app.post("/parse-xml-safe", async (req, res) => {
  if (req.body.includes("<!DOCTYPE") || req.body.includes("<!ENTITY")) {
    return res.status(400).send("DOCTYPE not allowed");
  }
  const result = await parseStringPromise(req.body);
  res.json(result);
});

How Hackers Exploit It

Attackers submit XML with a malicious DOCTYPE declaration, such as <!DOCTYPE foo [<!ENTITY xxe SYSTEM "file:///etc/passwd">]>. When the parser processes &xxe;, it reads /etc/passwd and includes the contents in the parsed result. Blind XXE variants exfiltrate data by sending file contents to an attacker-controlled server via HTTP requests.

How to Fix It

Disable DTD processing and external entity resolution in your XML parser. In most libraries, this is a configuration option. If your application does not need to process DTDs, reject any XML that contains DOCTYPE declarations. Prefer JSON over XML for new APIs. When XML is required, use a parser with secure defaults and keep it updated.

Frequently Asked Questions

What can an attacker do with an XXE vulnerability?
An attacker can read local files from the server (like /etc/passwd or application config files), perform server-side request forgery to reach internal services, cause denial of service through recursive entity expansion (the billion laughs attack), and in some cases execute commands via expect:// or php:// wrappers.
Is XXE still relevant if my API uses JSON?
If your API only accepts JSON, XXE is not a direct concern. However, if the server also accepts XML (even unintentionally through content-type negotiation), it may still be vulnerable. Ensure your server rejects XML content types if JSON is the only expected format.
How do I disable external entities in popular XML libraries?
In Java, set XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES to false. In Python's lxml, use defusedxml. In PHP, call libxml_disable_entity_loader(true). In Node.js with xml2js, the library is generally safe by default, but always verify and reject DOCTYPE declarations as an extra precaution.

Related Security Topics

Check Your Code for This Vulnerability

Run a free scan to check if your site is affected by xml external entity (xxe) attack.