HIGH broken access controlnestjsmutual tls

Broken Access Control in Nestjs with Mutual Tls

Broken Access Control in Nestjs with Mutual Tls — how this specific combination creates or exposes the vulnerability

Broken Access Control occurs when API endpoints fail to enforce proper authorization checks, allowing one user to access or modify another user's resources. In NestJS applications that use Mutual TLS (mTLS), the presence of client certificate authentication can create a false sense of security. Developers may assume that because the connection is authenticated via mTLS, authorization is unnecessary or can be simplified. This assumption is incorrect: mTLS provides identity, not permission.

When mTLS is used without explicit, per-request authorization, the application may inadvertently expose endpoints to BOLA/IDOR (Broken Level Authorization / Insecure Direct Object References). For example, an endpoint like GET /users/:userId/profile might validate the client certificate but then directly use the userId from the URL without verifying that the authenticated certificate belongs to that user. An attacker with a valid certificate could iterate over user IDs and access any profile, which middleBrick would flag as a BOLA finding under the Authorization check category.

Additionally, mTLS termination at a proxy or load balancer can complicate context propagation in NestJS. If the framework does not explicitly map the certificate subject or serial number to a user or role, the application may rely on default or missing identity data. This can lead to missing or misapplied role-based access controls (RBAC), especially when combining mTLS with other guards. The 12 parallel security checks in middleBrick test for these gaps by submitting unauthenticated probes that include manipulated identifiers and inspect whether the endpoint enforces ownership or scope checks, independent of transport-layer identity.

Real-world attack patterns relevant to this setup include IDOR via predictable numeric IDs and privilege escalation through misconfigured group claims embedded in certificates. Even with mTLS, endpoints that do not validate scope or tenant boundaries remain vulnerable to OWASP API Top 10 #1 Broken Object Level Authorization. middleBrick’s LLM/AI Security checks also ensure that certificate-based endpoints do not leak system prompts or allow prompt injection when API descriptions are exposed via documentation or introspection endpoints.

Mutual Tls-Specific Remediation in Nestjs — concrete code fixes

To fix Broken Access Control while using mTLS in NestJS, you must couple certificate validation with explicit authorization logic. Do not rely on the presence of a client certificate to enforce permissions. Instead, extract identity from the certificate and enforce ownership or role checks on every request.

Example: mTLS setup in NestJS with explicit identity mapping

import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { ClientProxy } from '@nestjs/microservices';

@Injectable()
export class CertificateGuard implements CanActivate {
  constructor(private readonly authService: AuthService) {}

  async canActivate(context: ExecutionContext): Promise<boolean> {
    const request = context.switchToHttp().getRequest();
    // Extract identity from the verified client certificate
    const cert = request.socket.getPeerCertificate();
    if (!cert || Object.keys(cert).length === 0) {
      throw new UnauthorizedException('Client certificate required');
    }
    // Map certificate fields to a user/role, e.g., using the serial number or subject CN
    const identity = await this.authService.mapCertificateToUser(cert);
    request.user = identity;
    return true;
  }
}

Example: Enforcing ownership in a user profile endpoint

import { Controller, Get, Param, UseGuards } from '@nestjs/common';
import { CertificateGuard } from './certificate.guard';
import { UserProfileService } from './user-profile.service';

@Controller('users')
export class UserProfileController {
  constructor(private readonly profileService: UserProfileService) {}

  @UseGuards(CertificateGuard)
  @Get(':userId/profile')
  async getProfile(@Param('userId') userId: string, @Req() req) {
    const currentUser = req.user; // mapped from certificate in guard
    if (currentUser.id !== userId) {
      throw new ForbiddenException('You cannot access this profile');
    }
    return this.profileService.getProfile(userId);
  }
}

Example: Applying scope and tenant checks with mTLS in a service

import { Injectable } from '@nestjs/common';

@Injectable()
export class ProjectService {
  async getProject(projectId: string, userId: string) {
    const project = await this.fetchProjectFromDb(projectId);
    if (!project) {
      throw new NotFoundException('Project not found');
    }
    // Ensure the user has access to this project
    const membership = await this.checkMembership(userId, project.tenantId);
    if (!membership) {
      throw new ForbiddenException('Access denied within scope');
    }
    return project;
  }

  private async checkMembership(userId: string, tenantId: string): Promise<boolean> {
    // Implement RBAC or ABAC check here using certificate-derived identity
    return true;
  }
}

These examples ensure that mTLS provides authentication, while explicit checks in guards and services enforce authorization. middleBrick’s CLI can validate these controls by scanning the endpoint with varied identifiers to confirm that access is restricted by ownership or scope, not merely by the presence of a certificate.

When integrating with external systems, ensure certificate-to-user mapping is centralized and auditable. The Pro plan’s continuous monitoring can alert you if a new endpoint lacks proper authorization guards, and the GitHub Action can fail builds when a scan detects missing ownership checks, helping you maintain posture as code evolves.

Frequently Asked Questions

Does mTLS alone prevent Broken Access Control in NestJS APIs?
No. Mutual TLS provides client authentication and transport-layer identity, but it does not enforce authorization. You must add explicit checks (guards or service logic) to verify that an authenticated subject has permission to access a specific resource. middleBrick tests for this gap by probing endpoints with manipulated identifiers while mTLS is present.
How can I map certificate fields to user roles in NestJS without hardcoding logic?
Centralize mapping in an AuthService that reads certificate fields such as subject or serial number and maps them to roles or user IDs, then inject this service into guards. Avoid embedding mapping logic in controllers. The MCP Server can help you validate that your certificate parsing and mapping behave consistently across endpoints during development.