Pii Leakage in Adonisjs with Api Keys
Pii Leakage in Adonisjs with Api Keys — how this specific combination creates or exposes the vulnerability
AdonisJS applications commonly use API keys to control access to routes and services. When API keys are handled without considering PII leakage risks, they can inadvertently expose sensitive user data in responses, logs, or error messages. A typical pattern is validating the key and attaching user metadata to the request object for downstream use. If that metadata includes personally identifiable information and is serialized into responses or debug output, PII can be disclosed to unauthorized clients.
For example, an API key validation middleware might fetch a user record and attach the full user object to ctx.state. If the user record contains fields such as email, name, or other identifiers, those fields can be included in JSON responses or rendered views without additional filtering. In an AdonisJS controller, directly returning the user instance or merging it into a response object can result in PII being sent to the client:
// Risk: returning user with PII fields directly
const ApiKey = use('App/Models/ApiKey')
class AuthController {
async authenticate ({ request, auth, response }) {
const apiKey = request.header('X-API-Key')
const keyRecord = await ApiKey.query()
.with('user')
.where('key', apiKey)
.first()
if (!keyRecord) {
return response.status(401).send({ error: 'Invalid API key' })
}
// PII leakage: user email and name may be exposed in the response
return response.send({ user: keyRecord.user })
}
}
Additionally, error handling and logging in AdonisJS can contribute to PII leakage when API key validation fails. If exceptions include user details or if logs capture request bodies and headers without sanitization, sensitive information such as email addresses or usernames may be stored or exposed through log aggregation tools. An example of risky logging is printing the entire request context or user payload during an authentication failure:
// Risk: logging user data alongside API key validation failure
const ApiKey = use('App/Models/ApiKey')
class AuthController {
async store ({ request, response, logger }) {
const { apiKey, data } = request.all()
logger.info('Incoming request', { apiKey, data, timestamp: new Date() })
const keyRecord = await ApiKey.findBy('key', apiKey)
if (!keyRecord) {
logger.warn('Invalid API key', { apiKey, userData: request.user() })
return response.status(401).send({ error: 'Unauthorized' })
}
}
}
Another vector involves OpenAPI/Swagger spec analysis combined with runtime findings. If the API specification documents endpoints that return user details without clearly indicating PII, and the runtime implementation exposes those fields, the discrepancy can lead to unintended disclosure. middleBrick detects such mismatches between spec definitions and observed behavior, including PII fields returned by endpoints that were not explicitly documented as sensitive.
SSRF and external data exposure can also interact with API key handling. An endpoint that accepts a URL supplied by the caller and uses an API key for outbound requests might inadvertently return responses containing PII from third-party services if the response is forwarded without filtering. Ensuring that responses are sanitized before being returned to the client is crucial to prevent leakage of sensitive fields like addresses, phone numbers, or government IDs.
Finally, the LLM/AI Security checks unique to middleBrick can identify scenarios where API keys or user data are exposed through AI-related endpoints, such as when an LLM response includes sensitive information embedded in tool calls or output. Even in non-AI contexts, ensuring that PII is not present in logs, error traces, or serialized objects remains essential for compliance with frameworks such as OWASP API Top 10 and GDPR.
Api Keys-Specific Remediation in Adonisjs — concrete code fixes
To mitigate PII leakage when using API keys in AdonisJS, implement strict response filtering and avoid attaching raw user records to request state. Instead of returning the entire user object, construct a minimal payload that excludes sensitive fields. This approach limits exposure while retaining necessary information for downstream logic.
// Safer: returning only non-PII fields
const ApiKey = use('App/Models/ApiKey')
class AuthController {
async authenticate ({ request, response }) {
const apiKey = request.header('X-API-Key')
const keyRecord = await ApiKey.query()
.with('user')
.where('key', apiKey)
.first()
if (!keyRecord) {
return response.status(401).send({ error: 'Invalid API key' })
}
// Explicitly exclude PII
const { email, ssn, phone, address } = keyRecord.user.serialize()
const safeUser = { id: keyRecord.user.id, username: keyRecord.user.username }
return response.send({ user: safeUser })
}
}
For logging, ensure that API keys and PII are redacted before being written to logs. Use a helper to sanitize sensitive fields and avoid logging full request bodies when they contain identifiers. Below is an example of structured logging that excludes sensitive data:
// Safe logging practice
const ApiKey = use('App/Models/ApiKey')
class AuthController {
async store ({ request, response, logger }) {
const apiKey = request.header('X-API-Key')
logger.info('Request received', { hasApiKey: !!apiKey })
const keyRecord = await ApiKey.findBy('key', apiKey)
if (!keyRecord) {
logger.warn('Invalid API key', { apiKey })
return response.status(401).send({ error: 'Unauthorized' })
}
// Proceed without logging user data
}
}
When using OpenAPI specs, annotate endpoints that return user-related data with explicit descriptions of PII fields and apply response filters consistently. If you generate client SDKs or documentation from the spec, ensure that sensitive fields are not inadvertently exposed. middleBrick can validate that runtime responses adhere to the documented schema and flag unexpected PII inclusion.
For applications integrating third-party services via outbound requests, apply output scanning to sanitize responses before they are processed or logged. This prevents PII from external APIs from persisting in your system. Combine this with rate limiting and input validation to reduce the risk of abuse and data exposure.
Developers can also leverage the CLI tool to automate scans and integrate checks into local workflows. Running middlebrick scan <url> against your AdonisJS endpoints can highlight endpoints that return PII and provide prioritized findings with remediation guidance. For teams with CI/CD pipelines, the GitHub Action can enforce security thresholds and prevent deployments when PII exposure risks are detected.
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 |