Data Exposure in Adonisjs with Mutual Tls
Data Exposure in Adonisjs with Mutual Tls
Mutual Transport Layer Security (mTLS) in AdonisJS can inadvertently contribute to data exposure when certificate-based authentication is present but application-layer data handling remains inconsistent. mTLS ensures both client and server authenticate each other using X.509 certificates, which strengthens channel security. However, if the application logic does not enforce strict authorization on sensitive data after authentication, mTLS alone does not prevent IDOR or BOLA-style access to resources. In AdonisJS, developers often rely on the presence of a valid client certificate to infer identity, but they may fail to verify whether that authenticated identity is permitted to access the specific resource requested.
For example, an endpoint like GET /api/users/:id might verify the client certificate and extract a subject field such as CN=user-123, but then directly use the route parameter :id to query the database without confirming that user-123 owns the record with the requested ID. This mismatch between transport-layer authentication (mTLS) and application-level authorization creates a data exposure window where one authenticated user can view or modify another user’s data. The risk is amplified when responses include sensitive fields such as email, phone number, or internal identifiers, and those fields are not filtered based on the authenticated identity derived from the certificate.
middleBrick detects this category of exposure by correlating mTLS authentication signals with data access patterns. It checks whether responses contain data that should be restricted based on the identity indicated by the client certificate, and whether authorization checks are consistently applied across endpoints. Findings often highlight missing ownership validation, overly broad role claims in certificate attributes, or inconsistent use of scoped queries. Remediation guidance emphasizes tying certificate-derived identities to data ownership models and applying per-request filters so that data exposure is limited strictly to what the authenticated subject is allowed to see.
Real-world CVEs in related frameworks illustrate the risk: vulnerabilities tagged under OWASP API Top 10 A1 (Broken Object Level Authorization) and A6 (Security Misconfiguration) often map to these patterns. For instance, improper handling of authenticated identity after mTLS handshake can lead to exposures similar to insecure direct object references, where predictable numeric IDs enable horizontal privilege escalation. Because mTLS is commonly perceived as providing complete security, such issues may remain undetected without active scanning that combines spec analysis and runtime testing, as performed by middleBrick in its unauthenticated black-box scans.
Mutual Tls-Specific Remediation in Adonisjs
To remediate data exposure risks in AdonisJS when using mTLS, you must enforce strict mapping between the certificate identity and data access scopes. This means that after the TLS handshake completes and the client certificate is validated, the application should extract a stable subject or serial identifier and use it to filter all data queries. Never rely on route parameters alone to determine data ownership; always cross-check the certificate-bound identity against the resource owner.
Below are concrete code examples that demonstrate how to implement mTLS-aware authorization in AdonisJS routes and providers.
1. Configure mTLS in the AdonisJS server
Enable client certificate verification at the server level. In start/server.ts, ensure the HTTPS server requests but does not necessarily require client certificates, allowing application logic to decide strictness:
import { HttpServer } from '@adonisjs/core/server'
export default class AppServer extends HttpServer {
protected ssl = {
cert: '/path/to/ca-bundle.pem',
key: '/path/to/server-key.pem',
requestCert: true,
rejectUnauthorized: false, // app will validate after inspecting cert
}
}
2. Extract identity from the client certificate
Create an around middleware or an auth provider that reads the peer certificate and normalizes the identity. This example uses a middleware that attaches the subject to the authentication guard:
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
export default class MtlsIdentityMiddleware {
public async handle(ctx: HttpContextContract, next: () => Promise<void>) {
const request = ctx.request
const socket = request.getRaw()
// @ts-ignore — peerCertificate is available on Node.js TLS socket
const cert = socket.getPeerCertificate()
if (!cert.subject) {
ctx.response.unauthorized('Client certificate missing subject')
return
}
// Normalize identity; prefer a custom SAN or CN field
const subject = cert.subject.CN || cert.subject.commonName
if (!subject) {
ctx.response.unauthorized('Client certificate subject is not recognized')
return
}
// Attach identity to the context for downstream use
ctx.auth.user = { mtlsSubject: subject } as any
await next()
}
}
3. Apply scoping in controllers
In your resource controller, use the mTLS-bound identity to filter queries. For a user profile endpoint, ensure the requested ID matches the certificate identity:
import User from 'App/Models/User'
export default class UsersController {
public async show({ params, auth }: HttpContextContract) {
const user = await User.query()
.where('id', params.id)
.where('mtls_subject', auth.user?.mttlsSubject)
.preload('profile')
.firstOrFail()
return user
}
}
4. Enforce scoping in providers and policies
For broader protection, implement a policy that checks ownership using the certificate identity before allowing updates or deletes:
import { BasePolicy } from '@ioc:Adonis/Core/Policy'
export default class ResourcePolicy extends BasePolicy {
public async update(ownerMtlsSubject: string, record: any) {
return record.mtls_subject === ownerMtlsSubject
}
public async delete(ownerMtlsSubject: string, record: any) {
return record.mtls_subject === ownerMtlsSubject
}
}
By combining mTLS authentication with explicit data ownership checks, you reduce the chance of data exposure across endpoints. middleBrick’s scans can validate that such scoping is consistently applied and flag endpoints that accept identifiers without verifying them against the certificate-derived identity.
Related CWEs: dataExposure
| CWE ID | Name | Severity |
|---|---|---|
| CWE-200 | Exposure of Sensitive Information | HIGH |
| CWE-209 | Error Information Disclosure | MEDIUM |
| CWE-213 | Exposure of Sensitive Information Due to Incompatible Policies | HIGH |
| CWE-215 | Insertion of Sensitive Information Into Debugging Code | MEDIUM |
| CWE-312 | Cleartext Storage of Sensitive Information | HIGH |
| CWE-359 | Exposure of Private Personal Information (PII) | HIGH |
| CWE-522 | Insufficiently Protected Credentials | CRITICAL |
| CWE-532 | Insertion of Sensitive Information into Log File | MEDIUM |
| CWE-538 | Insertion of Sensitive Information into Externally-Accessible File | HIGH |
| CWE-540 | Inclusion of Sensitive Information in Source Code | HIGH |