HIGH auth bypassadonisjsmutual tls

Auth Bypass in Adonisjs with Mutual Tls

Auth Bypass in Adonisjs with Mutual Tls — how this specific combination creates or exposes the vulnerability

Mutual Transport Layer Security (mTLS) requires both the client and the server to present valid certificates during the TLS handshake. In AdonisJS, mTLS is typically enforced at the reverse proxy or load balancer (e.g., NGINX, Traefik) or via Node.js HTTPS server options. If the application layer in AdonisJS does not independently verify the client certificate after the TLS handshake, an auth bypass can occur: an attacker who can terminate or spoof TLS (e.g., using a valid certificate issued by a trusted CA, or by connecting directly to the application port without mTLS enforcement) can send requests that appear authenticated to AdonisJS middleware.

Specifically, this happens when AdonisJS relies solely on the presence of req.client.authorized or a proxy-supplied header (like x-forwarded-cert) without validating the certificate chain, common name (CN), or extended key usage. AdonisJS route guards or middleware may check for the existence of a user derived from a session or token but skip verifying that the mTLS credential maps to an authorized identity. This mismatch between transport-layer authentication and application-level authorization enables horizontal or vertical privilege escalation (BOLA/IDOR) when an attacker uses a valid but low-privilege certificate to access another user’s resources.

Additionally, if the AdonisJS app accepts HTTP (not HTTPS) for development or legacy reasons while mTLS is expected only on HTTPS endpoints, an attacker can bypass mTLS entirely by sending requests over plain HTTP. This often occurs when route-level HTTPS enforcement is missing or when load balancers strip or mishandle TLS metadata. The OpenAPI/Swagger spec analysis integrated in middleBrick highlights such inconsistencies by cross-referencing security schemes with runtime behavior, helping to detect missing securitySchemes for mTLS and unauthenticated paths that should require client certificates.

Real-world attack patterns tied to this issue include:

  • Using a stolen or improperly scoped certificate to call administrative endpoints (BFLA/Privilege Escalation).
  • Exploiting missing certificate validation in custom AdonisJS policies to perform IDOR by iterating over user identifiers.
  • SSRF-induced mTLS bypass when internal services accept unverified client connections, leading to unauthorized access to downstream APIs.

These findings are surfaced by middleBrick’s 12 security checks, which run in parallel and map to compliance frameworks such as OWASP API Top 10 and PCI-DSS. The scanner tests unauthenticated attack surfaces and, when an OpenAPI spec is provided, resolves $ref definitions to ensure mTLS security schemes are consistently applied across operations.

Mutual Tls-Specific Remediation in Adonisjs — concrete code fixes

To securely implement mTLS in AdonisJS and prevent auth bypass, enforce client certificate validation at the application layer and align route security with transport-layer guarantees. Below are concrete steps and code examples.

1. Enforce mTLS at the HTTPS server level

When creating an HTTPS server in AdonisJS (e.g., in start.ts), require and verify client certificates using the requestCert and rejectUnauthorized options. This ensures only clients with valid, trusted certificates can complete the handshake.

import { HttpServer } from '@adonisjs/core/types'
import { createServer } from 'node:https'
import { readFileSync } from 'node:fs'

export default class HttpsServerProvider {
  public async register() {
    // Not used directly; server creation handled via provider or custom command
  }
}

// In a custom server bootstrap or provider
const httpsOptions = {
  key: readFileSync('path/to/server.key'),
  cert: readFileSync('path/to/server.crt'),
  ca: readFileSync('path/to/ca-bundle.crt'),
  requestCert: true,
  rejectUnauthorized: true, // Reject clients without valid cert
};

const server = createServer(httpsOptions, (req, res) => {
  // At this point, req.client contains the verified certificate
  const cert = req.client?.getRawCert?.()
  if (!cert) {
    res.statusCode = 403
    res.end('Client certificate required')
    return
  }
  // Optionally map certificate fields (e.g., CN) to user identity
  const username = extractUsernameFromCert(cert)
  req.user = { username, roles: mapRoles(username) }
  // Continue routing via AdonisJS adapter
})

server.listen(443, () => console.log('mTLS server listening on port 443'))

function extractUsernameFromCert(cert: Buffer): string {
  // Parse certificate subject CN (simplified example)
  const subject = cert.toString('utf8')
  const match = subject.match(/CN=([^,\/]+)/)
  return match ? match[1] : 'unknown'
}

2. Validate certificate details in middleware

Create an AdonisJS middleware that verifies certificate extensions (e.g., Extended Key Usage) and binds the certificate to a user in your database. This prevents unauthorized certificates even if TLS handshake succeeds.

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

export default class MtlsAuthMiddleware {
  public async handle({ request, response, auth }: HttpContextContract, next: () => Promise) {
    const cert = request.request.socket.getPeerCertificate?.()
    if (!cert || !cert.subject) {
      return response.forbidden({ error: 'Client certificate missing' })
    }

    // Example: ensure certificate has specific EKU or SAN
    const hasRequiredEku = checkEKU(cert.infoAccess)
    if (!hasRequiredEku) {
      return response.forbidden({ error: 'Insufficient certificate permissions' })
    }

    // Map CN or serial to a user and attach to auth
    const username = extractUsernameFromCert(cert.subject)
    const user = await User.findBy('username', username)
    if (!user) {
      return response.forbidden({ error: 'Certificate not authorized' })
    }

    await auth.use('api').login(user, { persist: false })
    await next()
  }
}

function checkEKU(infoAccess: any): boolean {
  // Implement actual EKU/SAN validation logic here
  return true
}

3. Align route-level security with mTLS

Ensure routes requiring mTLS are grouped and that insecure HTTP routes are restricted. Use AdonisJS route middleware to enforce that authenticated requests also present a verified certificate.

import Route from '@ioc:Adonis/Core/Route'

Route.group(() => {
  Route.get('/account', 'AccountController.show').middleware('mtls')
  Route.put('/account', 'AccountController.update').middleware('mtls')
}).prefix('api/v1').middleware({ mtls: true })

4. Validate and sanitize certificate-derived inputs

Treat certificate fields (e.g., CN, email) as untrusted input. Validate and sanitize before using them in queries to avoid injection and ensure proper mapping to your user model.

import { schema, rules } from '@ioc:Adonis/Core/Validator'

const certUserSchema = schema.create({
  username: schema.string({ trim: true }, [rules.alpha(), rules.minLength(3)]),
})

// After extracting and mapping certificate data
const validated = await validator.validate({ schema: certUserSchema, data: { username } })

5. Continuous monitoring and spec-driven checks

Use middleBrick’s CLI to scan your AdonisJS endpoints and verify that mTLS security schemes are correctly defined in OpenAPI 3.x and that all relevant paths require client certificates. The CLI can be run in scripts or CI/CD to fail builds if insecure routes are exposed.

# Example: scan an AdonisJS API endpoint from terminal
middlebrick scan https://api.example.com/openapi.json

For teams using GitHub Actions, add the security check as a PR gate; for advanced setups, use the MCP Server to scan APIs directly from IDEs like Cursor or Claude.

Related CWEs: authentication

CWE IDNameSeverity
CWE-287Improper Authentication CRITICAL
CWE-306Missing Authentication for Critical Function CRITICAL
CWE-307Brute Force HIGH
CWE-308Single-Factor Authentication MEDIUM
CWE-309Use of Password System for Primary Authentication MEDIUM
CWE-347Improper Verification of Cryptographic Signature HIGH
CWE-384Session Fixation HIGH
CWE-521Weak Password Requirements MEDIUM
CWE-613Insufficient Session Expiration MEDIUM
CWE-640Weak Password Recovery HIGH

Frequently Asked Questions

Can mTLS in AdonisJS prevent auth bypass if the application only checks proxy headers?
No. Relying only on proxy-supplied headers (e.g., x-forwarded-cert) without validating the certificate chain, CN, or EKU at the application layer can allow an attacker with a valid but low-privilege certificate to bypass authorization. Always validate the certificate details in AdonisJS middleware and bind them to verified user identities.
Does middleBrick fix auth bypass issues in AdonisJS mTLS setups?
middleBrick detects and reports misconfigurations such as missing client certificate validation and inconsistent security schemes. It provides prioritized findings with severity and remediation guidance, but it does not fix or patch the application. Use the CLI or MCP Server to integrate scans into your workflow and act on the guidance provided.