HIGH xml external entitiesadonisjsjwt tokens

Xml External Entities in Adonisjs with Jwt Tokens

Xml External Entities in Adonisjs with Jwt Tokens — how this specific combination creates or exposes the vulnerability

XML External Entity (XXE) injection occurs when an application processes XML input that references external entities, and the XML parser is configured to resolve them. In AdonisJS, this risk can intersect with JWT token handling when developers accept XML payloads (for example in advanced SAML or legacy SOAP integrations) and then embed information extracted from those payloads into JWT tokens, or accept JWTs that are XML-formatted (non-standard, but possible in niche federation scenarios).

In a typical AdonisJS application using JWT tokens, a developer might parse an incoming XML document to extract user attributes (such as roles or permissions), then include those attributes as claims when signing a JWT. If the XML parser resolves external entities, an attacker can supply an XML payload that references local files (e.g., file:///etc/passwd) or internal network resources via http:// or https:// URLs. Successful resolution can lead to sensitive data exposure, SSRF, or denial of service. Because the JWT is later used for authentication and authorization, the tainted claims may be trusted by downstream services, amplifying the impact.

The vulnerability is not inherent to JWT itself—JWTs are just a token format—but to the XML processing stage that precedes token creation or validation. AdonisJS does not include an XML parser in its core framework; however, if you introduce an XML library (such as xmldom or similar) and configure it to resolve external references, you create the condition for XXE. The risk is higher when the XML is used to enrich JWT claims, because the token may be accepted system-wide based on those claims.

Consider an endpoint that accepts an XML profile, reads a user role from it, and then issues a JWT containing that role. An attacker could submit an XML document with a malicious external entity that points to an internal metadata service. If the parser resolves the entity, the application may unintentionally disclose sensitive configuration data, and embed it into the JWT. Later, authorization checks that rely on the JWT role may be bypassed or misapplied.

Because middleBrick scans test the unauthenticated attack surface, it can surface indicators that an API accepts XML inputs and issues JWTs, highlighting the need to review XML parsing configurations. The scan does not modify your application; it reports findings with remediation guidance so you can adjust parsing behavior and claim construction to avoid introducing unsafe data into JWT tokens.

Jwt Tokens-Specific Remediation in Adonisjs — concrete code fixes

Remediation focuses on two areas: secure XML handling (or avoiding XML entirely) and ensuring JWT claims are derived from safe, validated sources. Below are concrete steps and code examples tailored for AdonisJS.

1. Avoid XML or disable external entity resolution

If you do not need XML, remove any XML parser dependencies. If you must parse XML, configure the parser to disallow external entities and DOCTYPE declarations. For example, using xmldom, avoid the default behavior and explicitly disable external resolution:

const { DOMParser } = require('@xmldom/xmldom');
const parser = new DOMParser({
  externalEntityReference: () => {
    // Reject any external entity reference
    return null;
  },
  errorHandler: {
    warning: (w) => { throw new Error(w); },
    error: (e) => { throw new Error(e); },
    fatalError: (e) => { throw new Error(e); }
  }
});

const xmlString = '<?xml version="1.0"?><user><role>admin</role></user>'; // example input
const document = parser.parseFromString(xmlString);
const roleNode = document.getElementsByTagName('role')[0];
const role = roleNode ? roleNode.textContent : null;

if (!role) {
  throw new Error('Invalid role in XML');
}

This ensures that entities such as &file; or &internal; are not resolved.

2. Validate and sanitize claims before signing JWTs

When constructing JWT tokens in AdonisJS, validate and sanitize all data that will become a claim. Do not directly embed data extracted from XML without strict checks:

const jwt = use('Adonis/Addons/Jwt');

function buildToken(user, roleFromXml) {
  // Whitelist acceptable roles; do not trust XML values blindly
  const validRoles = ['user', 'admin', 'editor'];
  const role = validRoles.includes(roleFromXml) ? roleFromXml : 'user';

  const payload = {
    sub: user.id,
    email: user.email,
    role: role,
    iat: Math.floor(Date.now() / 1000),
    exp: Math.floor(Date.now() / 1000) + (60 * 60) // 1 hour
  };

  return jwt.sign(payload, process.env.JWT_SECRET || 'change-me', { algorithm: 'HS256' });
}

// Example usage after safe parsing
const token = buildToken(currentUser, role);

By constraining roles to a known set, you prevent attackers from injecting privileged claims via XML external entities.

3. Secure JWT verification and claim usage

When verifying JWTs in AdonisJS, ensure you validate the signature, issuer, audience, and expiration. Do not trust claims that originated from unvalidated XML:

try {
  const payload = await jwt.verify(token, process.env.JWT_SECRET || 'change-me', { algorithms: ['HS256'] });
  // Use payload.sub, payload.role, etc., with confidence that they were signed by your service
  const user = await User.find(payload.sub);
  if (!user || user.role !== payload.role) {
    throw new Error('Insufficient permissions');
  }
  // proceed with authorized action
} catch (error) {
  throw new Error('Invalid token');
}

4. Use middleware to enforce safe authentication flows

In AdonisJS, create an authentication middleware that validates tokens and enforces role-based access without re-parsing XML on each request:

class AuthMiddleware {
  async handle({ request, auth }, next) {
    const token = request.header('authorization')?.replace('Bearer ', '');
    if (!token) {
      throw new Error('Unauthorized');
    }
    const payload = await auth.jwt.verify(token);
    request.authUser = payload;
    await next();
  }
}
module.exports = AuthMiddleware;

This approach keeps JWT handling separate from XML parsing and ensures that authorization relies on verified tokens rather than raw XML-derived data.

5. Monitoring and scanning

Use tools like middleBrick to scan your API endpoints. The scanner checks for indicators such as XML parsing behavior and JWT issuance patterns, and it reports findings with remediation guidance. The CLI can be run locally with middlebrick scan <url>, and the GitHub Action can be added to CI/CD pipelines to fail builds if risk scores drop below your chosen threshold.

Frequently Asked Questions

Can a JWT token itself contain XML that leads to XXE?
JWTs are typically base64url-encoded JSON and are not XML, so they cannot directly carry XML external entities. However, if your application accepts XML payloads and embeds data from those payloads into JWT claims, the XML parsing step is where XXE risk exists. The JWT itself is a carrier for claims, not the source of XML parsing.
How can I verify that my XML parser in AdonisJS does not resolve external entities?
Review your parser configuration to ensure external entity resolution is explicitly disabled. For example, when using xmldom, set an externalEntityReference handler that returns null and configure error handlers to throw on unexpected input. You can also test by providing an XML payload that references an external entity and confirming that the entity is not resolved and no network request is made; middleBrick scans can surface risky parsing patterns to help identify insecure configurations.