HIGH insecure designadonisjsmutual tls

Insecure Design in Adonisjs with Mutual Tls

Insecure Design in Adonisjs with Mutual Tls — how this specific combination creates or exposes the vulnerability

Insecure design in an AdonisJS application using mutual TLS (mTLS) often arises from treating mTLS as the sole authentication mechanism while neglecting authorization, input validation, and secure defaults. mTLS provides transport-layer identity by requiring both client and server to present valid certificates. However, if the application does not enforce additional checks—such as verifying certificate attributes, mapping certificates to users or roles, and applying strict authorization—mTLS alone cannot prevent vertical or horizontal privilege escalation (BOLA/IDOR) and can give a false sense of security.

For example, an AdonisJS route that relies only on mTLS may trust the certificate’s Common Name (CN) or subject without validating it against an authorization model. If the certificate maps to a user ID used in database queries without further checks, an attacker who compromises a low-privilege certificate can iterate over identifiers to access other users’ resources (BOLA/IDOR). This is an insecure design because mTLS handles authentication but not authorization, and the application must implement both.

Another insecure pattern is failing to validate and sanitize inputs even when mTLS is in place. An attacker might embed malicious payloads in request bodies or query parameters, and if the application does not apply input validation, property-based authorization, or safe data handling, injection or business logic flaws can occur. For instance, an endpoint that accepts an id parameter and directly uses it in an AdonisJS Lucid query without validation could enable IDOR if the identifier is not scoped to the requesting certificate’s mapped entity.

Insecure design also appears in certificate lifecycle management. Hardcoding certificate paths, weak file permissions on certificate stores, or failing to rotate certificates can expose private keys. If the AdonisJS app loads certificates via environment variables without runtime protection, misconfigured environments might leak sensitive material. Additionally, missing revocation checks (e.g., CRL or OCSP) can allow compromised certificates to remain trusted, which is an insecure operational design even when mTLS is technically implemented.

These issues map to broader categories such as OWASP API Top 10 API1:2023 Broken Object Level Authorization and API2:2023 Broken User Authentication. PCI-DSS and SOC2 controls also emphasize the need for strong access control and key management. middleBrick scans detect such insecure design patterns by correlating OpenAPI/Swagger specs (with full $ref resolution) against runtime behavior, flagging missing authorization on authenticated endpoints, insufficient input validation, and unsafe certificate usage.

Mutual Tls-Specific Remediation in Adonisjs — concrete code fixes

To remediate insecure design when using mutual TLS in AdonisJS, combine mTLS enforcement with explicit authorization, input validation, and secure certificate handling. Below are concrete code examples that demonstrate a secure approach.

1. Enforce mTLS in AdonisJS HTTP server

Configure the AdonisJS server to require client certificates. In start/server.ts, set up the HTTPS server with request certificate verification:

import { HttpServer } from '@adonisjs/core/build/standalone';
import { readFileSync } from 'fs';

const server = new HttpServer();

server.app.use(async (ctx, next) => {
  const req = ctx.request;
  // Ensure a client certificate is present and validated by TLS layer
  if (!req.socket.getPeerCertificate()) {
    ctx.response.status = 401).send({ error: 'Client certificate required' });
    return;
  }
  await next();
});

server.start({
  https: {
    key: readFileSync('path/to/server-key.pem'),
    cert: readFileSync('path/to/server-cert.pem'),
    ca: readFileSync('path/to/ca-chain.pem'),
    requestCert: true,
    rejectUnauthorized: true,
  },
});

export default server;

This ensures the TLS layer rejects connections without a valid client certificate signed by the trusted CA, reducing the risk of unauthenticated access.

2. Map certificate identity to application authorization

Do not rely solely on the certificate CN; extract a stable identifier (e.g., a serial number or subjectAltName) and map it to an application user or role. Use an authorization check before accessing resources:

import { HttpContextContract } from '@adonisjs/core/http';
import User from 'App/Models/User';

export default class ProfilesController {
  public async show({ request, params, auth }: HttpContextContract) {
    const clientCert = request.socket.getPeerCertificate();
    // Map certificate serial to user
    const user = await User.query()
      .where('cert_serial', clientCert.serialNumber)
      .preload('roles')
      .firstOrFail();

    // Enforce ownership or role-based checks
    if (user.id !== auth.user?.id && !user.roles.some(r => r.name === 'admin')) {
      throw new Error('Unauthorized');
    }

    return user;
  }
}

This prevents BOLA/IDOR by ensuring that certificate identity is mapped to an authorization model and that users can only access their own data unless explicitly permitted.

3. Validate and sanitize all inputs

Even with mTLS, validate and sanitize inputs to prevent injection and logic flaws. Use AdonisJS schema validation:

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

const profileSchema = schema.create({
  id: schema.number([
    () => rules.unsigned(),
    () => rules.exists({ table: 'profiles', column: 'id' }),
  ]),
});

export default class ProfilesController {
  public async show({ request, params }: HttpContextContract) {
    const payload = await request.validate({ schema: profileSchema });
    const profile = await Profile.findOrFail(payload.id);
    return profile;
  }
}

This ensures that resource identifiers are valid and scoped, mitigating injection and authorization bypass risks.

4. Secure certificate storage and rotation

Avoid hardcoding certificate paths. Use runtime secrets and restrict file permissions. For example, load certificates from a secure volume with limited access and rotate them periodically. In containerized deployments, use secrets management to inject paths and keys at runtime without exposing them in configuration files.

5. Implement revocation checks

Where feasible, perform revocation checks during the TLS handshake or as an additional application-layer verification to handle compromised certificates promptly.

Frequently Asked Questions

Does mTLS alone prevent IDOR in AdonisJS applications?
No. mTLS authenticates the client but does not enforce authorization. Without mapping certificate identities to application roles and implementing per-request authorization checks, an attacker with a valid certificate can still perform IDOR by manipulating resource identifiers.
How does middleBrick detect insecure design with mTLS in AdonisJS?
middleBrick scans the OpenAPI/Swagger spec (with full $ref resolution) and runtime behavior to identify endpoints that rely on mTLS for authentication but lack proper authorization, input validation, and secure certificate handling, highlighting insecure design patterns and providing remediation guidance.