HIGH pii leakageadonisjsjwt tokens

Pii Leakage in Adonisjs with Jwt Tokens

Pii Leakage in Adonisjs with Jwt Tokens — how this specific combination creates or exposes the vulnerability

AdonisJS is a Node.js web framework that commonly uses JSON Web Tokens (JWT) for stateless authentication. When JWTs are used without care, personally identifiable information (PII) can be inadvertently exposed through token content, logs, or error messages, and through mismatched validation and serialization practices.

JWTs are often stored in the payload with user identifiers and profile fields. If a token includes fields such as email, name, or other direct PII, any service that can read or intercept the token can extract that data. Even if the token is cryptographically signed, exposure of the token (e.g., via logs, browser storage, or insecure transmission) leads to PII leakage because the payload is typically base64-encoded and not encrypted.

In AdonisJS, developers sometimes attach sensitive user properties directly to the token payload during creation. For example, including a full user object or email in the JWT payload means that any component with token access can decode and view that information. Tokens may also be logged inadvertently in application logs, especially if debug or error reporting prints the authorization header or token contents. Another risk occurs when token validation does not strictly enforce scopes or claims, allowing broader access than intended and increasing the surface for PII exposure through token replay or misuse.

Additionally, if the application serializes user data into the token without filtering PII, and that token is transmitted over non-HTTPS channels, interception becomes a realistic threat. Even with HTTPS, storing tokens in insecure client-side storage (e.g., local storage) can lead to token theft and subsequent PII exposure. AdonisJS applications must ensure that tokens carry only necessary identifiers, avoid embedding sensitive fields, and enforce strict transport and storage practices to mitigate this risk.

Jwt Tokens-Specific Remediation in Adonisjs — concrete code fixes

To reduce PII leakage risk with JWTs in AdonisJS, limit token contents to minimal identifiers, avoid storing sensitive data, and enforce secure transmission and storage practices. Below are concrete code examples showing how to create and verify tokens safely.

When generating a token, include only a user ID and necessary metadata, and exclude email or other PII. Use environment-based secret management and short expiration times to reduce exposure windows.

import { base64url } from 'jose';
import { DateTime } from 'luxon';
import { JwtProvider } from '@ioc/Adonis/Addons/Jwt';

export default class AuthController {
  public async login({ request, auth, response }) {
    const user = await auth.authenticate();
    const token = await JwtProvider.use('jwt').issue({
      sub: String(user.id),           // minimal identifier, not PII
      iat: Math.floor(DateTime.local().toSeconds()),
      exp: Math.floor(DateTime.local().plus({ hours: 1 }).toSeconds()),
      scopes: ['read', 'write'],      // least-privilege scope
    });

    // Send only the token via secure, httpOnly cookie or Authorization header
    response.cookie('token', token.toString(), {
      httpOnly: true,
      secure: true,
      sameSite: 'strict',
    });
    return response.json({ ok: true });
  }
}

When verifying tokens, ensure that the payload is not used to expose PII and that claims are validated strictly. Do not trust decoded payload for authorization decisions without re-checking server-side permissions.

import { HttpContextContract } from '@ioc/Adonis/Core/HttpContext';
import { JwtProvider } from '@ioc/Adonis/Addons/Jwt';

export default class UserController {
  public async me({ request, response }) {
    const token = request.headers().authorization?.replace('Bearer ', '');
    if (!token) {
      return response.unauthorized();
    }

    try {
      const payload = await JwtProvider.use('jwt').verify(token);
      // Use only the subject ID to fetch user; do not rely on payload PII
      const user = await User.findOrFail(payload.sub);
      return response.json({ id: user.id, username: user.username });
    } catch (error) {
      return response.unauthorized();
    }
  }
}

Additional remediation steps include:

  • Use short-lived tokens and refresh token rotation to limit the usefulness of leaked tokens.
  • Transmit tokens only over HTTPS and enforce HSTS to prevent downgrade attacks.
  • Store tokens in httpOnly, Secure, SameSite=Strict cookies when possible, avoiding local storage.
  • Audit logs to ensure tokens or authorization headers are not printed in application or error logs.
  • Apply strict CORS and CSRF protections to reduce cross-origin leakage risks.

Related CWEs: dataExposure

CWE IDNameSeverity
CWE-200Exposure of Sensitive Information HIGH
CWE-209Error Information Disclosure MEDIUM
CWE-213Exposure of Sensitive Information Due to Incompatible Policies HIGH
CWE-215Insertion of Sensitive Information Into Debugging Code MEDIUM
CWE-312Cleartext Storage of Sensitive Information HIGH
CWE-359Exposure of Private Personal Information (PII) HIGH
CWE-522Insufficiently Protected Credentials CRITICAL
CWE-532Insertion of Sensitive Information into Log File MEDIUM
CWE-538Insertion of Sensitive Information into Externally-Accessible File HIGH
CWE-540Inclusion of Sensitive Information in Source Code HIGH

Frequently Asked Questions

Can JWT payloads contain PII safely if they are base64-encoded?
No. Base64 encoding is not encryption; anyone who obtains the token can decode the payload and read any PII it contains. Avoid placing PII in JWT payloads.
How can I prevent token leakage in logs within an AdonisJS application?
Ensure authorization headers and tokens are never printed in logs or error responses. Use structured logging that filters sensitive fields and configure AdonisJS error handlers to omit auth details.