HIGH xml external entitiesrestify

Xml External Entities in Restify

How Xml External Entities Manifests in Restify

XML External Entity (XXE) vulnerabilities in Restify applications arise when an XML parser processes external entity references without proper safeguards. Restify itself does not include a built-in XML parser; developers typically integrate third-party libraries like libxmljs, xml2js, or body-parser (with XML support) to handle application/xml payloads. The vulnerability manifests when these parsers are configured to resolve external entities, allowing attackers to reference local files, internal network resources, or trigger denial-of-service conditions.

A common vulnerable pattern in Restify routes involves using libxmljs without disabling external entity processing. For example, a Restify server that manually parses XML request bodies with libxmljs.parseXml() inherits the library's default behavior of enabling external entities. An attacker can send a malicious XML payload containing a DOCTYPE declaration with an external entity that reads sensitive files from the server's filesystem:

const restify = require('restify');
const libxmljs = require('libxmljs');

const server = restify.createServer();

server.post('/api/process-xml', (req, res, next) => {
  let xml = '';
  req.on('data', chunk => xml += chunk);
  req.on('end', () => {
    try {
      // VULNERABLE: external entities are enabled by default in libxmljs
      const doc = libxmljs.parseXml(xml);
      // Processing the parsed document...
      res.send({ status: 'success' });
    } catch (err) {
      res.send(500, { error: err.message });
    }
    return next();
  });
});

server.listen(8080);

When this endpoint receives an XXE payload like:

<?xml version="1.0"?>
<!DOCTYPE foo [
  <!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<root>&xxe;</root>

the parser resolves &xxe; to the contents of /etc/passwd. If the application subsequently includes this data in its response (e.g., by serializing the parsed document back to XML or JSON), the attacker gains unauthorized access to sensitive system files. Even without direct data exfiltration, XXE can be used for server-side request forgery (SSRF) by referencing internal network resources, such as http://169.254.169.254/latest/meta-data/ in cloud environments, or for denial-of-service via billion-laughs attacks.

Restify's built-in bodyParser plugin, when configured for XML, uses xml2js by default—a library that does not process external entities due to its reliance on the sax parser. However, if developers override this with a custom parser or explicitly use libxmljs (which offers richer XPath and XSLT features), the risk reappears. The vulnerability is confined to endpoints that accept XML input; JSON-only APIs are unaffected.

Restify-Specific Detection

Detecting XXE in Restify applications requires both manual code review and dynamic testing. Manually, inspect all routes that parse XML for the use of vulnerable parsers or unsafe configurations. Look for:

  • Direct usage of libxmljs.parseXml() or libxmljs.parseXmlContext() without the { noext: true } option.
  • Custom middleware that collects raw request bodies (via req.on('data')) and passes them to XML parsers.
  • Third-party Restify plugins that wrap XML parsing libraries and may expose parser options.

Dynamic testing involves sending XXE payloads to XML-accepting endpoints and observing responses for file content, error messages, or behavioral changes. For example, a payload that references file:///etc/hosts might return that file's contents if the application echoes parsed data. Another test uses an external entity to trigger an SSRF: <!ENTITY xxe SYSTEM "http://attacker-controlled.com/">. If the server makes an outbound request to the attacker's domain, it confirms XXE and SSRF potential.

Automated scanners like middleBrick simplify this process. When you submit a Restify API endpoint URL to middleBrick, it performs a black-box scan that includes an XXE check. The scanner sends a suite of XXE payloads (including file inclusion, SSRF, and billion-laughs variants) to endpoints that accept XML (identified via Content-Type: application/xml or similar). It then analyzes responses for signs of successful exploitation, such as the presence of expected file contents (e.g., root:x:0:0 from /etc/passwd), DNS/HTTP callbacks, or parser error messages that leak information. The scan takes 5–15 seconds and produces a per-category risk score, with XXE findings categorized under Input Validation or Data Exposure depending on impact.

middleBrick also correlates runtime findings with OpenAPI specifications if provided. If your Restify API documents XML request schemas (e.g., via Swagger), middleBrick cross-references these with the actual endpoint behavior to identify mismatches that could indicate XXE risks not apparent from the spec alone.

Restify-Specific Remediation

Remediating XXE in Restify centers on disabling external entity processing in any XML parser used. The most straightforward fix is to rely on Restify's built-in bodyParser plugin, which uses xml2js—a parser that does not support external entities by default. Simply enable XML parsing via:

server.use(restify.plugins.bodyParser({
  mapParams: true,
  // The 'xml' option is enabled by default when Content-Type is XML
}));

This approach requires no additional configuration and safely handles XML payloads. However, if your use case demands libxmljs (e.g., for XPath queries), you must explicitly disable external entities in every parsing call. The libxmljs library provides the noext option for this purpose:

const doc = libxmljs.parseXml(xmlString, { noext: true });

For custom middleware that manually collects request bodies, update the parsing logic to include this option. For example, the vulnerable route from the first section becomes:

server.post('/api/process-xml', (req, res, next) => {
  let xml = '';
  req.on('data', chunk => xml += chunk);
  req.on('end', () => {
    try {
      // FIXED: disable external entities
      const doc = libxmljs.parseXml(xml, { noext: true });
      res.send({ status: 'success' });
    } catch (err) {
      res.send(500, { error: err.message });
    }
    return next();
  });
});

Additionally, validate that all dependencies are up-to-date; some older versions of XML parsers may have different default settings or vulnerabilities. As a defense-in-depth measure, consider implementing input validation that rejects XML payloads containing DOCTYPE declarations entirely—though this may break legitimate use cases. Finally, if your Restify API does not require XML, remove XML parsing support altogether and enforce application/json via middleware.

After applying fixes, rescan the endpoint with middleBrick to verify the XXE risk is resolved. The Pro plan's continuous monitoring can alert you if the risk reappears due to code changes or new vulnerabilities.

Frequently Asked Questions

Does middleBrick fix XXE vulnerabilities automatically?
No. middleBrick is a detection and reporting tool only. It identifies XXE vulnerabilities and provides remediation guidance (e.g., 'set noext: true in libxmljs'), but it does not modify your code or infrastructure. You must implement the fixes manually in your Restify application.
Can middleBrick detect XXE in Restify APIs that use custom XML parsers?
Yes. middleBrick's black-box scanner sends XXE payloads to any endpoint that accepts XML (based on Content-Type headers). It does not need to know which parser you use; it tests for exploitation outcomes like file disclosure or SSRF. The scan works with Restify apps regardless of whether they use bodyParser, libxmljs, or other parsers.