HIGH vulnerable componentsadonisjsfirestore

Vulnerable Components in Adonisjs with Firestore

Vulnerable Components in Adonisjs with Firestore — how this specific combination creates or exposes the vulnerability

When AdonisJS applications interact with Google Cloud Firestore, several common patterns introduce security risks that map directly to the 12 security checks run by middleBrick. Because Firestore rules and AdonisJS route/handler design operate in different trust domains, misconfigurations can expose data or allow privilege escalation even when the application appears to enforce authorization.

One frequent issue is over-permissive Firestore security rules combined with incomplete server-side checks in AdonisJS controllers. For example, a route like GET /users/:id might validate that the authenticated user ID matches the route parameter, but if the Firestore rule uses request.auth != null without also verifying ownership of the document path, a horizontally privileged user can read another user’s record by guessing IDs. This scenario maps to BOLA/IDOR and BFLA/Privilege Escalation checks.

Another vulnerability pattern involves unvalidated input used to construct document references. If an AdonisJS handler passes user-controlled strings directly into Firestore paths, an attacker can leverage dot notation or collection group queries to access restricted collections. For instance, a field such as roomId taken from request parameters could be concatenated into a reference like firestore.collection('rooms').doc(roomId). Without strict allow-listing of document IDs and path components, this enables data exposure and can bypass intended tenant isolation.

Property authorization gaps also appear when Firestore documents contain sensitive fields like role, isAdmin, or internal pointers. If the AdonisJS layer sends entire documents to the client without stripping or redacting these fields, Data Exposure findings are likely. Even with rules that limit read access, the client may infer higher-privilege operations by observing presence or values of administrative flags. middleBrick’s Property Authorization and Data Exposure checks detect these patterns by correlating runtime responses with rule and schema expectations.

SSRF risks emerge when Firestore document fields contain URLs or hostnames that are later used in server-side operations such as webhooks or outbound HTTP calls. If an attacker can inject a malicious URI into a Firestore field (for example, via a compromised admin interface or an unsafe import), the backend may make internal network calls that reveal metadata or reach restricted services. The SSRF check in middleBrick tests for such scenarios by observing outbound interactions initiated from document data.

Unsafe Consumption and LLM/AI Security become relevant if Firestore-stored content is fed into LLM prompts without sanitization. For example, if user-generated data stored in a notes collection is concatenated into a system prompt for an LLM endpoint, system prompt leakage or prompt injection may occur. middleBrick’s LLM-specific probes, including system prompt leakage detection and active prompt injection testing, are designed to surface these risks when Firestore data influences LLM inputs.

Firestore-Specific Remediation in AdonisJS — concrete code fixes

Remediation focuses on strict server-side authorization, input validation, and defense-in-depth when using Firestore with AdonisJS. Always treat Firestore security rules as a necessary but insufficient layer; enforce ownership and scope checks in your AdonisJS handlers as well.

1. Enforce strict ownership checks in handlers

For a route that reads a user document, resolve the authenticated UID from the session or token and compare it with the document path before constructing the Firestore reference. Do not rely on route parameters alone.

import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import { Firestore, doc, getDoc } from 'firebase/firestore'

export default class UsersController {
  constructor(
    private db: Firestore
  ) {}

  public async showMe({ auth, params }: HttpContextContract) {
    const user = auth.user!
    // Ensure the requested ID matches the authenticated UID
    if (params.id !== user.id) {
      throw new Error('Unauthorized')
    }
    const userRef = doc(this.db, 'users', user.id)
    const snapshot = await getDoc(userRef)
    if (!snapshot.exists()) {
      throw new Error('Not found')
    }
    // Strip sensitive fields before returning
    const { passwordHash, ssoSecrets, ...safeData } = snapshot.data()
    return safeData
  }
}

2. Validate and allow-list document identifiers

Never directly concatenate user input into Firestore paths. Use allow-lists or strict regex validation for document IDs and collection segments.

import { schema } from '@ioc:Adonis/Core/Validator'

const roomIdSchema = schema.string({}, {
  format: 'regex',
  regex: /^[a-zA-Z0-9_-]{1,100}$/,
})

// In a controller
public async joinRoom({ request, auth }: HttpContextContract) {
  const body = request.validate({ schema: roomIdSchema })
  const roomRef = doc(this.db, 'rooms', body.roomId)
  // additional tenant/isolation checks if applicable
  const snap = await getDoc(roomRef)
  // proceed safely
}

3. Apply principle of least privilege to Firestore rules

Define rules that scope access to user-specific paths and avoid wildcards that permit broad reads. Combine rules with server-side checks for robust security.

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{userId} {
      allow read, write: if request.auth != null && request.auth.uid == userId;
    }
    match /publicItems/{itemId} {
      allow read: if true;
      allow write: if request.auth != null && request.auth.token.role == 'admin';
    }
  }
}

4. Sanitize and redact sensitive fields

When returning Firestore documents to clients, explicitly remove or rename fields that convey privilege or internal references.

export function sanitizeUserDoc(data: any) {
  if (!data) return data
  // Remove fields that should never reach the client
  const { passwordHash, apiKey, internalNotes, ...publicData } = data
  return publicData
}

5. Neutralize SSRF via controlled outbound behavior

If Firestore documents contain URLs used for webhooks or external calls, validate and restrict destinations. Use an allow-list of domains and avoid direct execution of stored URLs from privileged contexts.

import axios from 'axios'

export async function safeWebhookFromDoc(docData: any) {
  if (!docData?.webhookUrl) return
  const allowedDomains = new Set(['https://api.example.com/webhook'])
  const url = new URL(docData.webhookUrl)
  if (!allowedDomains.has(url.origin)) {
    throw new Error('Blocked disallowed webhook target')
  }
  await axios.post(url.toString(), docData.payload)
}

6. Treat Firestore content as untrusted before LLM ingestion

Before using Firestore data in prompts, especially system prompts, sanitize and validate to prevent prompt injection and system prompt leakage. middleBrick’s LLM security checks can help identify risky patterns when such integrations are in scope.

export function buildPromptFromFirestore(doc: any) {
  const safeInstructions = doc.instructions?.replace(/\\n\\s*/g, ' ')?.trim()
  if (!safeInstructions) {
    throw new Error('Invalid instruction data')
  }
  return `You are a helpful assistant. Follow these instructions: ${safeInstructions}`
}

Frequently Asked Questions

Does Firestore's native security replace server-side checks in AdonisJS?
No. Firestore rules are a necessary layer but should be complemented by server-side authorization in AdonisJS to prevent IDOR, privilege escalation, and data exposure.
How can I prevent stored Firestore URLs from causing SSRF in my AdonisJS backend?
Validate and allow-list all outbound destinations, avoid direct execution of URLs from privileged workflows, and inspect document content before using it in network calls.