Excessive Data Exposure in Adonisjs with Mutual Tls
Excessive Data Exposure in Adonisjs with Mutual Tls
Excessive Data Exposure occurs when an API returns more data than the client needs, often including sensitive fields such as internal identifiers, passwords, or PII. In Adonisjs, this commonly arises from broad Eloquent or Lucid model serialization without explicit field selection. When Mutual TLS (mTLS) is used for client authentication, developers may assume the transport is fully protected and reduce other safeguards, inadvertently increasing the impact of data overexposure. mTLS ensures the client is who they claim to be, but it does not limit what the server returns; a compromised or misauthorized client can still receive excessive information if the endpoint lacks strict output controls.
With mTLS, the server validates the client certificate during the TLS handshake, but application-layer logic remains responsible for scoping data. In Adonisjs, routes and controllers often serialize entire model instances. For example, a route that fetches a user profile might return the full user record, including fields like password_reset_token, email_verification_code, or internal relational data. Even with mTLS, if a client certificate is mistakenly issued to a less-privileged party or if certificate revocation is not handled, that client could retrieve more data than intended. This becomes a compounded risk when endpoints do not enforce per-request authorization checks, such as ensuring the requesting client is allowed access only to specific subsets of data.
Another dimension is the exposure of metadata or debug information that Adonisjs may include in development environments. Stack traces, query logs, or verbose validation messages can reveal internal structures or field names, aiding an attacker in crafting further attacks. With mTLS in place, an attacker who possesses a valid certificate might target endpoints that return excessive payloads, leveraging the trusted connection to exfiltrate data in smaller, less noticeable chunks. The combination of mTLS and unchecked serialization can therefore create a false sense of security, where transport-layer protections obscure application-layer data exposure issues.
To identify this during a scan, middleBrick checks whether responses include unnecessary fields and whether authorization is applied at the property level. Findings often highlight endpoints that return full model instances without filtering, or that rely solely on mTLS for access control without implementing fine-grained permissions. Remediation focuses on explicit field selection, context-aware serialization, and ensuring that each endpoint applies the correct authorization checks regardless of transport-layer client validation.
Mutual Tls-Specific Remediation in Adonisjs — concrete code fixes
Remediation centers on ensuring that data exposure controls are independent of mTLS and that serialization is explicit. Below are concrete patterns for Adonisjs that reduce excessive data exposure while working alongside mTLS.
1. Explicit field selection in serializers
Use Adonisjs serializers to define exactly which fields are exposed. This prevents accidental leakage of sensitive attributes.
// resources/serializers/UserProfileSerializer.ts
import { DateTime } from 'luxon'
import { BaseSerializer } from '@ioc:Adonisjs/Addons/Serialization'
export default class UserProfileSerializer extends BaseSerializer {
public serialize(user: any) {
return {
id: user.id,
username: user.username,
fullName: user.full_name,
avatarUrl: user.avatar_url,
role: user.role,
// Do NOT include: password_reset_token, email_verification_code, internal_notes
createdAt: DateTime.fromJSDate(user.created_at.toJSDate()).toISO(),
}
}
}
In your controller, apply the serializer explicitly:
// start/controllers/UsersController.ts
import User from 'App/Models/User'
import UserProfileSerializer from 'App/Serializers/UserProfileSerializer'
export default class UsersController {
public async show({ params, request }: HttpContextContract) {
const user = await User.findOrFail(params.id)
// Even with mTLS, only return the serialized subset
return new Response(user.serialize(new UserProfileSerializer()))
}
}
2. Enforce per-request authorization
Do not rely on mTLS to determine data scope. Use policies or guards to ensure a client can only access allowed fields and relations.
// start/policies/UserPolicy.ts
import { BasePolicy } from '@ioc:Adonisjs/Addons/Policy'
import User from 'App/Models/User'
export default class UserPolicy extends BasePolicy {
public async viewProfile(clientUser: User, targetUserId: string) {
// Ensure the authenticated (via mTLS) client can only view their own profile
return clientUser.id === targetUserId
}
}
Apply the policy in the route:
// start/routes.ts
import Route from '@ioc:Adonisjs/Core/Route'
import UserPolicy from 'App/Policies/UserPolicy'
Route.get('/users/:id', 'UsersController.show').authorize('user.viewProfile')
3. Disable development debug outputs in production
Ensure debug and stack traces are not returned, as they can expose field names and structures even when mTLS is used.
// start/kernel.ts
import { HttpContextContract } from '@ioc:Adonisjs/Core/HttpContext'
export default class Kernel {
public async handle(error: any, ctx: HttpContextContract) {
if (error.name === 'ValidationError' || error.name === 'InvalidContext') {
// Return minimal error details regardless of mTLS client trust
ctx.response.status(error.status || 400).send({ error: 'Invalid request' })
return
}
// Fallback handling...
}
}
4. Validate and sanitize inputs to prevent indirect exposure
Even with mTLS, validate incoming data to avoid leaking information through errors or logs.
// start/validators/ProfileValidator.ts
import { schema, rules } from '@ioc:Adonisjs/Core/Validator'
export default class ProfileValidator {
public schema = schema.create({
username: schema.string({}, [rules.alpha(), rules.maxLength(20)]),
})
public async validate(data: any) {
// Avoid verbose messages that could hint at internal fields
return this.schema.validate(data)
}
}
5. Combine mTLS with rate limiting and anomaly detection
While not directly removing excessive data, rate limiting reduces the potential for bulk extraction via a trusted certificate.
// start/routes.ts
import Route from '@ioc:Adonisjs/Core/Route'
Route.group(() => {
Route.get('/users/:id', 'UsersController.show').rateLimit({ max: 100, windowMs: 60 })
}).prefix('api').middleware(['mTLS']) // assuming mTLS is enforced at a higher layer
Related CWEs: propertyAuthorization
| CWE ID | Name | Severity |
|---|---|---|
| CWE-915 | Mass Assignment | HIGH |