Xml External Entities in Hapi with Jwt Tokens
Xml External Entities in Hapi with Jwt Tokens — how this specific combination creates or exposes the vulnerability
XML External Entity (XXE) injection occurs when an application processes XML input and permits external entity references, allowing an attacker to read local files, trigger SSRF, or cause denial of service. Hapi is a Node.js framework that can parse XML payloads when configured to do so, for example via plugins or libraries such as hapi-joi-validation or custom parsers that accept XML. If the XML parser is not hardened and Jwt Tokens are handled in a way that mixes untrusted XML data with token validation, the attack surface expands.
Consider a scenario where an API endpoint accepts both XML and a JWT for authorization. The endpoint might parse an XML body to extract parameters while also reading a JWT from an Authorization header. If the XML parser is vulnerable to XXE and the JWT validation logic trusts data derived from or influenced by the XML (for example, mapping XML-extracted values into claims used during JWT verification), an attacker can exploit the combination.
An illustrative attack flow: an attacker sends a request with an Authorization bearer token containing a JWT and an XML body with a malicious external entity referencing file:///etc/passwd. If the server’s XML parser resolves the entity before or during processing of the JWT context—such as using XML-derived values to influence which key is used to verify the JWT signature, or embedding extracted XML data into JWT claims—confidential data can leak. XXE can also be chained with SSRF to probe internal services that are reachable from the Hapi runtime, especially if JWT validation involves introspection or calls to internal endpoints identified from XML content.
Insecure parser configuration is a common root cause. For instance, using a library that enables external entity resolution by default, or constructing a parser with features like processDocDef or entity expansion enabled, allows attackers to define entities that read resources. Even if Jwt Tokens are validated by a separate library, any shared configuration, logging, or error handling that exposes parsed XML data can aid an attacker. For example, verbose errors that include entity content or system identifiers can reveal file paths or internal network details that aid further exploitation.
Because middleBrick tests unauthenticated attack surfaces and includes Input Validation and Data Exposure checks, it can surface weak XML configurations and risky handling of Jwt Tokens in endpoints that accept both XML and bearer tokens. Findings often highlight missing entity disallowlists, unsafe parser features, and insufficient separation between authorization data and user-controlled XML. Remediation focuses on hardening the XML parser and ensuring JWT validation operates on a verified, trusted source of data rather than values influenced by external XML.
Jwt Tokens-Specific Remediation in Hapi — concrete code fixes
Remediation centers on two goals: eliminate XXE risks in XML parsing and ensure Jwt Tokens are validated using trusted, untampered data. Below are concrete practices and code examples for Hapi.
1. Disable external entities in XML parsing
Use a secure XML parser configuration that disallows external entities and DOCTYPE declarations. For example, with xmldom, avoid enabling features that permit external references:
const { DOMParser } = require('@xmldom/xmldom');
const parser = new DOMParser({
errorHandler: {
warning: () => {/* ignore */},
error: () => {/* ignore */},
fatalError: () => {/* ignore */}
},
// Ensure no external DTDs are loaded
externalSubsetResolver: null
});
const xml = parser.parseFromString(req.payload, 'text/xml');
If you use libxmljs, avoid entity expansion features and do not load external DTDs:
const libxml = require('libxmljs');
const doc = libxml.parseXml(req.payload, { noblanks: true, noent: false, nocdata: false, entityLoader: null });
2. Validate and sanitize data before Jwt Token use
Ensure that any data extracted from XML is not used to influence JWT verification. For example, do not use XML-extracted values to select a signing key or to construct claims without strict validation.
Standard Jwt Token verification with hapi-auth-jwt2 and joi should rely on the token itself and a trusted key:
const Hapi = require('@hapi/hapi');
const Jwt = require('@hapi/hoek/lib/jwt');
const validate = async (decoded, request, h) => {
// Perform trusted checks, e.g., verify scope/roles from decoded JWT only
if (!decoded.scope) {
return { isValid: false };
}
return { isValid: true, credentials: { scope: decoded.scope } };
};
const server = Hapi.server({ port: 4000, host: 'localhost' });
server.register(require('hapi-auth-jwt2'), (err) => {
if (err) throw err;
server.auth.strategy('jwt', 'jwt', {
key: process.env.JWT_PUBLIC_KEY,
validate: validate,
verifyOptions: { algorithms: ['RS256'] }
});
server.auth.default('jwt');
});
3. Apply defense-in-depth measures
- Set
processDocDefand external subset resolution to false. - Do not merge user-controlled XML fields into JWT claims or headers; if you must, apply strict allowlists and canonicalization before signing/verification.
- Use middleware to reject requests with suspicious XML constructs (e.g.,
<!ENTITY) before they reach parsers.
middleBrick can detect weak XML handling and risky Jwt Tokens usage by scanning endpoints that accept both XML and bearer tokens. Its checks align with OWASP API Top 10 and can map findings to compliance frameworks. The CLI tool (middlebrick scan <url>) and GitHub Action help integrate these safeguards into development workflows, while the Web Dashboard tracks changes over time.