HIGH out of bounds writeadonisjsmutual tls

Out Of Bounds Write in Adonisjs with Mutual Tls

Out Of Bounds Write in Adonisjs with Mutual Tls

An Out Of Bounds Write occurs when code writes data past the boundaries of a buffer or data structure, which can corrupt memory or cause undefined behavior. In AdonisJS, this risk can surface when handling raw buffers, streams, or typed arrays, especially when requests are authenticated via Mutual TLS (mTLS). With mTLS, the server validates the client certificate before processing the request. If the application then reads the client certificate or request body into a fixed-size buffer without proper length checks, an attacker can supply a crafted payload that triggers an out-of-bounds write.

Consider a scenario where an AdonisJS route processes a client certificate’s Common Name (CN) or a custom header and copies it into a fixed-length buffer. Without validating the length, an oversized value can overflow into adjacent memory. Because mTLS terminates the TLS layer before the application sees the request, developers may assume the transport is inherently safe and skip input validation. This false sense of security can lead to unchecked copying of certificate fields or uploaded file chunks, creating an out-of-bounds condition.

Real-world examples include using Node.js Buffer operations that do not enforce boundaries or passing unchecked data to native addons. An attacker could exploit this to corrupt the process heap, potentially leading to arbitrary code execution or denial of service. The vulnerability is not in mTLS itself but in how the application handles data after the TLS layer has authenticated the client.

middleBrick scans can detect unsafe handling of buffers and certificate metadata by correlating OpenAPI specifications with runtime behavior, identifying endpoints that accept large or untrusted payloads without adequate validation. This is especially important for mTLS-enabled APIs where unauthenticated scanning endpoints still expose the application surface once the TLS handshake completes.

Mutual Tls-Specific Remediation in Adonisjs

Remediation focuses on validating all inputs derived from the mTLS context and applying strict bounds checking before any write operation. Treat certificate fields and headers as untrusted data.

1. Validate certificate fields before use

Do not assume the CN or SAN lengths are small. Explicitly check length and sanitize before copying into fixed-size structures.

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

export default class CertificatesController {
  public async store({ request, response }: HttpContextContract) {
    const clientCert = request.$ssl?.clientCert
    if (!clientCert) {
      return response.badRequest({ error: 'Client certificate required' })
    }

    // Validate CN length before using it
    const cn = clientCert.subject.commonName
    const safeCn = this.sanitizeCommonName(cn)

    // Use safeCn in business logic instead of raw cn
    return response.ok({ commonName: safeCn })
  }

  private sanitizeCommonName(cn?: string): string {
    if (!cn) return ''
    // Limit to a reasonable length, e.g., 256 characters
    return cn.length > 256 ? cn.substring(0, 256) : cn
  }
}

2. Use constant-time comparison for sensitive values

When comparing certificate fingerprints or secrets, use a constant-time comparison to avoid timing-based side channels that could aid an attacker in crafting out-of-bounds inputs.

import { timingSafeEqual } from 'crypto'

export function safeBufferCompare(a: Buffer, b: Buffer): boolean {
  if (a.length !== b.length) {
    return false
  }
  // timingSafeEqual requires buffers of the same length
  return timingSafeEqual(a, b)
}

3. Sanitize uploaded file buffers

If your mTLS API accepts file uploads, validate the buffer size and content type before processing. Do not write directly to fixed-size buffers.

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

const fileSchema = schema.create({
  file: schema.file.optional({}, {
    size: '4mb',
    extnames: ['jpg', 'png', 'pdf']
  })
})

export const validateFile = async (ctx: HttpContextContract) => {
  await fileSchema.validateOrThrow(ctx)
  const file = ctx.request.file('file')
  if (file) {
    const buffer = await file.toBuffer()
    // Process buffer safely; do not assume size is bounded by extnames alone
    if (buffer.length > 0 && buffer.length <= 4 * 1024 * 1024) {
      // Safe processing
    }
  }
}

4. Enforce strict schema for JSON payloads

Even with mTLS, JSON payloads must be validated against a strict schema to prevent oversized strings that could lead to out-of-bounds conditions when used internally.

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

const payloadSchema = schema.create({
  metadata: schema.object({
    description: schema.string.optional({}, { trim: true, escape: false }),
    tags: schema.array.optional(schema.string.optional({}, { trim: true }))
  })
})

export const validatePayload = async (ctx: HttpContextContract) => {
  await payloadSchema.validateOrThrow(ctx)
  // Safe to use validated payload
}

Frequently Asked Questions

Can middleBrick detect out-of-bounds write risks in mTLS-enabled APIs?
Yes, middleBrick scans unauthenticated attack surfaces and can identify unsafe handling of buffers and certificate metadata that may lead to out-of-bounds writes, even when mTLS is used for authentication.
Does mTLS eliminate the need for input validation in AdonisJS?
No. Mutual TLS authenticates the client but does not validate the content of requests. Application-level input validation and bounds checking remain essential to prevent out-of-bounds writes and other injection or corruption issues.