HIGH information disclosureadonisjsmutual tls

Information Disclosure in Adonisjs with Mutual Tls

Information Disclosure in Adonisjs with Mutual Tls

Mutual Transport Layer Security (mTLS) in AdonisJS involves both the server and the client presenting certificates during the TLS handshake. When mTLS is configured incorrectly or when application logic does not properly validate or handle the authenticated client identity, it can lead to information disclosure. This specific combination—AdonisJS application logic interacting with mTLS connections—can expose sensitive data through several channels.

First, relying solely on the presence of a client certificate without verifying its details can leak information about the certificate chain, subject distinguished name (DN), or serial number in application logs, error messages, or debugging output. If AdonisJS logs the client certificate subject after a successful mTLS handshake without sanitization, an attacker who can read the logs may map which clients are connecting, effectively enumerating authorized entities.

Second, AdonisJS applications often use the client certificate to derive authorization decisions or to look up user profiles (e.g., mapping a certificate subject to an internal user ID). If these operations are performed insecurely—such as constructing file paths or database queries using raw certificate fields without strict validation—an attacker may exploit path traversal or injection patterns to access files or data belonging to other clients. This mapping step can inadvertently disclose whether specific certificates are recognized, aiding enumeration.

Third, misconfigured mTLS can cause the server to accept connections where the client certificate is optional or not validated on certain routes. AdonisJS middleware that conditionally enforces mTLS may expose endpoints that fall back to less secure authentication mechanisms, inadvertently revealing sensitive application data to unauthenticated or low-privilege actors. For example, an admin route intended for mTLS-only access might still serve data when accessed without a client certificate if route guards are not uniformly applied.

Consider an AdonisJS controller that retrieves a user profile based on the certificate subject:

import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import User from 'App/Models/User'

export default class ProfilesController {
  public async show({ request, response }: HttpContextContract) {
    const cert = request.$ssl?.clientCert
    if (!cert) {
      return response.unauthorized()
    }
    // Risky: using raw certificate fields in queries
    const user = await User.findBy('tls_subject', cert.subject)
    if (!user) {
      return response.notFound()
    }
    // Potential information disclosure in error or logs
    console.log('Serving profile for', cert.subject)
    return user.toJSON()
  }
}

In this example, if cert.subject contains machine-readable identifiers and is used directly in a database query, subtle differences in behavior (timing, error messages) can reveal whether a given subject is valid. Additionally, logging the subject in plaintext can expose which clients are active. An attacker with network access to logs or error reporting channels can infer the set of authorized mTLS principals.

Furthermore, if the TLS termination happens at a proxy or load balancer in front of AdonisJS, and the application trusts headers like x-client-cert without verifying the connection is internal and authenticated, an attacker could spoof these headers to trigger information disclosure. AdonisJS might then expose stack traces, debug information, or verbose error pages that include environment details, file paths, or configuration snippets.

To mitigate these risks, treat mTLS as a transport-layer guarantee and not an authorization token by itself. Always validate and sanitize any data derived from client certificates before using it in business logic or logging. Ensure uniform enforcement of mTLS across routes and avoid fallback authentication paths that weaken the intended protection.

Mutual Tls-Specific Remediation in Adonisjs

Secure mTLS usage in AdonisJS requires strict validation of client certificates, careful handling of certificate-derived data, and consistent enforcement across routes. The following practices and code examples demonstrate how to reduce information disclosure risks.

1. Validate and sanitize certificate fields before use. Do not rely on raw subject strings for authorization or queries. Instead, map certificates to known identities using a controlled lookup.

2. Avoid logging sensitive certificate details. If logging is necessary for auditing, redact or hash identifiable fields.

3. Enforce mTLS uniformly across all sensitive routes and avoid conditional or optional enforcement that can create weak links.

4. Use environment configuration to control trusted certificate authorities and revocation checks where applicable, ensuring the server only trusts certificates from known issuers.

Here is a hardened example that maps a client certificate to a user via a controlled lookup and avoids direct use of raw certificate fields in queries:

import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import User from 'App/Models/User'
import { logger } from '@ioc:Adonis/Core/Logger'

export default class SecureProfilesController {
  private certificateFingerprint(cert: any): string {
    // Compute a stable fingerprint for audit logging without exposing raw data
    return require('crypto')
      .createHash('sha256')
      .update(cert.fingerprint || '')
      .digest('hex')
  }

  public async show({ request, response, auth }: HttpContextContract) {
    const cert = request.$ssl?.clientCert
    if (!cert) {
      return response.unauthorized()
    }

    // Validate certificate fields strictly
    const subject = cert.subject
    if (!subject || typeof subject !== 'string') {
      logger.warn('Invalid certificate subject format')
      return response.badRequest({ error: 'Invalid certificate' })
    }

    // Map subject to user via a controlled mapping (e.g., database or config)
    // Example mapping stored in environment or a trusted configuration
    const allowedMappings: Record = {
      'CN=alice,O=Example,C=US': 1,
      'CN=bob,O=Example,C=US': 2,
    }
    const userId = allowedMappings[subject]
    if (!userId) {
      logger.info(`Rejected unknown certificate: ${this.certificateFingerprint(cert)}`)
      return response.forbidden({ error: 'Access denied' })
    }

    // Fetch user by primary key, not by raw certificate data
    const user = await User.find(userId)
    if (!user) {
      return response.notFound()
    }

    // Safe audit logging
    logger.info(`Serving profile for user ${user.id} cert=${this.certificateFingerprint(cert)}`)
    return user.toJSON()
  }
}

For applications behind a proxy that handles TLS, configure AdonisJS to trust the internal connection and validate headers explicitly:

import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'

export default class ProxyAwareController {
  public async secureAction({ request, response }: HttpContextContract) {
    const clientCert = request.header('x-forwarded-client-cert')
    // Validate the header format and signature if provided by the proxy
    if (!clientCert || !clientCert.startsWith('SHA256=')) {
      return response.unauthorized()
    }
    // Further validation and mapping as needed
  }
}

Ensure your AdonisJS middleware stack enforces mTLS for all sensitive endpoints, and review route definitions to prevent accidental exposure. By treating certificate data as untrusted input and mapping it through a controlled, auditable process, you minimize the risk of information disclosure while preserving the benefits of mutual authentication.

Frequently Asked Questions

What specific information disclosure risks arise from using raw certificate subjects in AdonisJS queries?
Using raw certificate subjects in queries can enable attackers to infer valid identities through timing differences or error messages, and logging subjects may expose which clients are authenticated.
How can mTLS be enforced consistently across all routes in an AdonisJS application?
Apply mTLS checks in a centralized middleware that runs for all sensitive routes, avoid optional or conditional enforcement, and validate certificate fields before using them in business logic or logging.