Pii Leakage in Adonisjs with Mutual Tls
Pii Leakage in Adonisjs with Mutual Tls — how this specific combination creates or exposes the vulnerability
AdonisJS, a Node.js web framework, often handles sensitive payloads such as personally identifiable information (PII) in requests and responses. When mutual TLS (mTLS) is used, the assumption is that transport-layer authentication and encryption prevent unauthorized access. However, PII leakage can still occur due to framework behavior, middleware misconfiguration, or improper error handling, even when mTLS is enforced.
In an mTLS setup, both client and server present certificates. AdonisJS can be configured to require client certificates, but if the application logs request bodies, stack traces, or query details without redaction, PII may be exposed in logs or error outputs. For example, a route that accepts JSON containing email or phone numbers might inadvertently include these fields in console logs or unhandled rejection traces, which are accessible to users with limited access to logging systems.
Another scenario involves the serialization of responses. If AdonisJS controllers or serializers include sensitive fields (such as ssn or dob) in JSON output without filtering, and those responses are cached or monitored, PII can be exposed to unauthorized consumers. Middleware that attaches request context for debugging may also propagate PII across services if correlation IDs are stored with payload data.
Moreover, mTLS ensures identity, not data minimization. An authenticated client with valid certificates might still submit PII in parameters that are not intended for certain endpoints. Without explicit validation and schema-based sanitization, AdonisJS will process and potentially echo these fields in responses or logs, creating leakage pathways. This is especially relevant when integrating third-party services that require broad payload access but should only receive a subset of PII.
Real-world patterns include routes that bind request bodies directly to models or DTOs without stripping sensitive fields, or using global exception handlers that expose full request details in error messages. Even with mTLS, such practices can lead to PII leakage through verbose error pages or debug endpoints that are inadvertently exposed in development-like configurations.
Mutual Tls-Specific Remediation in Adonisjs — concrete code fixes
To mitigate PII leakage while using mutual TLS in AdonisJS, apply targeted remediation at the framework and application level. These fixes focus on input validation, response filtering, and safe error handling, while preserving mTLS benefits.
1. Enforce mTLS in AdonisJS server configuration
Configure the HTTPS server to request and validate client certificates. Use AdonisJS hook or provider to customize the TLS options. Below is a concrete example using the built-in HTTP server with TLS options in start/server.ts:
import { HttpServer } from '@adonisjs/core/http'
import { readFileSync } from 'fs'
export const http = new HttpServer({
ssl: {
key: readFileSync('path/to/server.key'),
cert: readFileSync('path/to/server.crt'),
ca: readFileSync('path/to/ca.crt'),
requestCert: true,
rejectUnauthorized: true,
},
})
This setup ensures that only clients with valid certificates signed by the trusted CA can establish a connection. The requestCert and rejectUnauthorized flags enforce mutual authentication without altering application logic.
2. Sanitize and validate incoming PII before processing
Use schema validation to explicitly allow only necessary fields and strip or transform PII at the boundary. With AdonisJS v5+ using Lucid or custom validation, define a schema that excludes sensitive fields from being persisted or echoed:
import { schema } from '@ioc:Adonis/Core/Validator'
const userSchema = schema.create({
email: schema.string.optional(),
phone: schema.string.optional(),
// Exclude ssn, dob, or other PII unless explicitly required
})
export const userValidator = (ctx) => {
const payload = ctx.request.validate({
schema: userSchema,
})
// Proceed with sanitized payload
return payload
}
For routes that must handle PII, apply additional masking in middleware before logging or forwarding data. This prevents raw PII from appearing in console logs or diagnostic snapshots.
3. Secure error handling and response serialization
Customize the exception handler to avoid exposing request details. In app/Exceptions/Handler.ts, filter stack traces and redact PII fields from error messages:
import { ExceptionHandler } from '@ioc:Adonis/Core/ExceptionHandler'
export default class CustomExceptionHandler extends ExceptionHandler {
public handle(error, ctx) {
// Redact PII from error messages
const safeMessage = error.message?.replace(/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/g, '[REDACTED]') || 'An error occurred'
if (error.name === 'ValidationException') {
ctx.response.badRequest({ error: safeMessage, code: error.code })
return
}
// Generic safe response
ctx.response.status(error.status || 500).send({ error: safeMessage })
}
}
This approach ensures that even if an error includes user input, sensitive PII fields such as emails are replaced before being logged or returned.
4. Control logging and debugging output
Avoid logging full request bodies in development or production. If logging is necessary, use a formatter that strips PII:
import { logger } from '@poppinss/dev-utils'
function safeLog(data: any) {
const { email, phone, ssn, ...rest } = data
logger.info('Request metadata', rest)
}
Integrate this pattern in route handlers or event listeners to prevent PII from persisting in log stores.
5. Enforce data minimization at integration boundaries
When mTLS routes involve third-party callbacks or webhooks, validate that only necessary data is shared. Use transformation layers to extract required non-PII fields and discard the rest before further processing.
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 |