HIGH pii leakageadonisjsfirestore

Pii Leakage in Adonisjs with Firestore

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

AdonisJS is a Node.js web framework that encourages explicit data modeling and structured request handling. When integrating AdonisJS with Google Cloud Firestore, PII leakage commonly arises from mismatched data access patterns and overly permissive Firestore rules combined with incomplete runtime validation in AdonisJS controllers. Firestore stores documents in collections; if queries return entire documents or subcollections without field-level filtering, sensitive fields such as email, phone, government ID, or internal metadata can be exposed to the client-side or logs.

In AdonisJS, developers often use Lucid ORM-style models or raw Firestore SDK clients. If models or services do not explicitly select fields before serialization, and Firestore security rules rely only on broad read access for authenticated users, an attacker can retrieve PII through legitimate API endpoints. For example, an endpoint like GET /users/me might return the full user document, including fields like ssn, password_reset_token, or two_factor_secret, because the controller does not strip sensitive keys and the Firestore rules do not restrict fields by path.

Another scenario involves Firestore subcollections or map fields that contain nested PII. If an AdonisJS service recursively serializes a document without depth control or field whitelisting, sensitive nested objects can be exposed. Additionally, Firestore array-contains queries or composite indexes used in AdonisJS services may inadvertently reveal PII in query logs or error messages, especially when debugging information is returned to the caller.

The LLM/AI Security checks in middleBrick highlight risks where system prompt leakage or unsafe consumption patterns expose model outputs containing PII. In AdonisJS-Firestore integrations, this can occur if LLM-related endpoints return raw Firestore documents that include private user data. Without explicit field filtering and strict runtime validation, Firestore’s flexible schema becomes a vector for PII leakage.

To detect such issues, scanning an AdonisJS endpoint that interacts with Firestore using middleBrick can uncover missing field-level authorization, excessive data exposure in Firestore rules, and insecure serialization patterns. The scanner evaluates authentication, data exposure, and property authorization checks, producing findings with severity and remediation guidance mapped to frameworks like OWASP API Top 10.

Firestore-Specific Remediation in Adonisjs — concrete code fixes

Remediation focuses on explicit field selection, strict Firestore rules, and secure serialization in AdonisJS. Always retrieve only required fields from Firestore and sanitize responses before sending to the client.

1. Selective Field Retrieval in AdonisJS Service

Create a service that queries Firestore and returns a controlled subset of fields. Use the Fire Admin SDK with service account credentials in your AdonisJS app. Below is a secure example using the Firestore Node.js client.

import { Firestore } from '@google-cloud/firestore';

const firestore = new Firestore();

export class UserService {
  static async getUserPublicProfile(uid: string) {
    const userRef = firestore.collection('users').doc(uid);
    const snapshot = await userRef.get();
    if (!snapshot.exists) {
      return null;
    }
    const data = snapshot.data();
    // Explicitly pick safe fields
    return {
      uid: data?.uid,
      displayName: data?.displayName,
      photoUrl: data?.photoUrl,
      email: data?.email,
    };
  }
}

2. Firestore Security Rules: Least Privilege by Field

Define rules that restrict read access to specific fields based on request.auth.uid and request.resource.data. Avoid allowing read access to entire collections or documents.

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{userId} {
      allow read: if request.auth != null && request.auth.uid == userId
                  && request.resource.data.keys().hasAll(['uid', 'displayName', 'photoUrl', 'email'])
                  && request.resource.data.keys().size() == 4;
      allow write: if request.auth != null && request.auth.uid == userId
                   && request.resource.data.keys().hasAll(['displayName', 'photoUrl', 'email'])
                   && request.resource.data.keys().size() == 3;
    }
    match /private/{document=**} {
      allow read: if false;
    }
  }
}

3. Controller-Level Field Stripping and Validation

In your AdonisJS controller, validate and strip fields before serialization. Use schema validation (e.g., Joi or Yup) to ensure only expected fields are present.

import { schema } from '@ioc:Adonis/Core/Validator';
import UserService from 'App/Services/UserService';

const userSchema = schema.create({
  uid: schema.string(),
  displayName: schema.string.optional(),
  photoUrl: schema.string.optional(),
  email: schema.string.optional([ rules.email() ]),
});

export default class UsersController {
  public async show({ params, response }) {
    const user = await UserService.getUserPublicProfile(params.uid);
    if (!user) {
      return response.notFound();
    }
    // Validate and return safe shape
    const payload = userSchema.validate(user);
    return response.ok(payload);
  }
}

4. Avoiding Subcollection and Nested PII Exposure

If using subcollections (e.g., userPosts), ensure nested reads are gated by ownership and field selection. Do not recursively serialize entire documents.

export class PostService {
  static async getUserPostsPublic(uid: string) {
    const postsRef = firestore.collection('users').doc(uid).collection('posts');
    const snapshot = await postsRef.get();
    return snapshot.docs.map(doc => {
      const data = doc.data();
      return {
        id: doc.id,
        title: data?.title,
        publishedAt: data?.publishedAt,
      };
    });
  }
}

5. Continuous Monitoring and Scanning

Use middleBrick to scan your AdonisJS endpoints regularly. The CLI can be integrated into scripts or the GitHub Action to fail builds if PII exposure patterns are detected. The dashboard tracks changes over time and provides prioritized findings with remediation guidance.

By combining selective querying, strict Firestore rules, and schema validation in AdonisJS, you reduce the attack surface for PII leakage. These steps align with data exposure controls in frameworks such as OWASP API Top 10 and support compliance mappings for PCI-DSS and GDPR.

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

How does middleBrick detect PII leakage in AdonisJS Firestore integrations?
middleBrick scans unauthenticated attack surfaces and runs 12 parallel security checks including Data Exposure and Property Authorization. It correlates Firestore document structures returned by AdonisJS endpoints with expected field sets, flagging missing field-level filtering, overly permissive rules, and unsafe serialization that can expose PII.
Can Firestore security rules alone prevent PII leakage in AdonisJS?
Firestore rules are necessary but not sufficient on their own. AdonisJS controllers must also explicitly select fields and validate output shape. middleBrick’s scans evaluate both runtime behavior and spec-defined rules, highlighting gaps where rules exist but are bypassed or where controllers expose full documents.