HIGH cors wildcardadonisjsfirestore

Cors Wildcard in Adonisjs with Firestore

Cors Wildcard in Adonisjs with Firestore — how this specific combination creates or exposes the vulnerability

A misconfigured CORS wildcard in an AdonisJS application that serves Firestore-backed endpoints can unintentionally grant broad cross-origin access to authenticated Firestore resources. When cors.allowedOrigins is set to a wildcard (e.g., *) while credentials are allowed, browsers permit any origin to present authenticated requests on behalf of a user. If Firestore security rules rely solely on Firebase Authentication UID checks and do not also enforce origin constraints, a malicious site can leverage the user’s active session to make unauthorized Firestore reads or writes.

In this setup, AdonisJS typically acts as a proxy or API layer that authenticates requests and then communicates with Firestore using a service account or Firebase Admin SDK. If CORS permits any origin and the response includes credentials (e.g., cookies or Authorization headers), an attacker’s page can invoke these endpoints with the victim’s authenticated context. The Firestore calls will succeed from the browser because the user’s Firebase ID token is included, and the backend does not validate the request origin. This exposes data that Firestore rules alone might restrict, effectively bypassing intended access boundaries.

For example, an attacker’s page can load a script that calls /api/firestore/user-data. If AdonisJS does not validate the Origin header and forwards the request with a valid ID token, Firestore processes the request as the authenticated user. Even if Firestore rules limit reads to a user’s own document path, the broader CORS policy enables the attacker to reach endpoints that should be origin-restricted. The wildcard removes a critical layer of origin-based enforcement, and the browser’s same-origin policy does not block the request when credentials are present.

Additionally, preflight requests can reveal permitted methods and headers, aiding reconnaissance. An OPTIONS request to the AdonisJS endpoint with Access-Control-Request-Method: POST and Access-Control-Request-Headers: authorization can confirm that credentials and custom headers are accepted. Combined with a wildcard, this signals that any site can initiate authenticated interactions, increasing risk of cross-site request forgery-like abuse against Firestore operations.

Firestore-Specific Remediation in Adonisjs — concrete code fixes

Remediation focuses on tightening CORS in AdonisJS and adding origin checks where appropriate, while ensuring Firestore rules remain the final authority. Below are concrete code examples for AdonisJS and Firestore rules that align with secure patterns.

AdonisJS CORS Configuration

Configure CORS to a strict allowlist and avoid wildcard origins when credentials are used. In start/cors.ts, specify exact origins and selectively allow credentials.

import { cors } from '@ioc:Adonis/Addons/Cors'

export default cors({
  enabled: true,
  origin: ['https://your-trusted-domain.com', 'https://app.your-trusted-domain.com'],
  allowCredentials: true,
 allowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
  allowHeaders: ['Content-Type', 'Authorization'],
})

This configuration ensures only known origins can make authenticated requests to your AdonisJS endpoints, reducing the attack surface presented to malicious sites.

Firestore Security Rules with Origin Context

While Firestore rules cannot directly inspect HTTP Origin headers in browser contexts, you can enforce origin checks indirectly by validating custom tokens or using Firebase Authentication with additional application-layer metadata. Combine strict Firestore rules with your AdonisJS layer to reject requests that do not originate from trusted sources.

Example Firestore rule that restricts access to a user’s own documents:

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

To further reduce risk, store an allowed origin list in Firestore or via Remote Config and have your AdonisJS middleware check the Origin header before constructing or proxying Firestore calls. If the origin is not permitted, respond with a 403 and do not forward the request.

AdonisJS Middleware Origin Validation

Add a server-side middleware in AdonisJS to validate the Origin header for Firestore-bound routes. This ensures that even if a browser sends credentials, requests from untrusted origins are blocked before reaching Firestore.

import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'

export default class OriginValidationMiddleware {
  public async handle({ request, response, next }: HttpContextContract) {
    const allowedOrigins = ['https://your-trusted-domain.com', 'https://app.your-trusted-domain.com']
    const origin = request.headers().origin

    if (origin && allowedOrigins.includes(origin)) {
      response.header('Access-Control-Allow-Origin', origin)
    } else {
      return response.status(403).send({ error: 'Forbidden origin' })
    }

    await next()
  }
}

Register this middleware on routes that interact with Firestore. This complements CORS settings and provides defense-in-depth by ensuring that only expected origins reach your backend logic.

Secure Token Handling

When using service accounts in AdonisJS to access Firestore, avoid exposing service account keys to the browser. Keep all Firestore interactions server-side and ensure that the browser only receives short-lived, user-specific tokens via secure, HttpOnly cookies or Authorization headers that are not leaked to third-party origins.

Example of initializing Firestore Admin in AdonisJS and fetching user data securely:

import { initializeApp, cert } from 'firebase-admin/app'
import { getFirestore } from 'firebase-admin/firestore'

const serviceAccount = require('../../../service-account.json')

if (!initializeApp.apps.length) {
  initializeApp({
    credential: cert(serviceAccount),
  })
}

const db = getFirestore()

export async function getUserData(uid: string) {
  const doc = await db.collection('users').doc(uid).get()
  if (!doc.exists) {
    throw new Error('User data not found')
  }
  return doc.data()
}

This server-side approach ensures that sensitive service account credentials never reach the client, and Firestore rules continue to govern document-level access based on authenticated UID.

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 Firestore security rules alone prevent issues caused by a CORS wildcard in AdonisJS?
No. Firestore rules validate data access based on authentication state and UID, but they do not inspect the HTTP Origin header. A CORS wildcard with credentials can allow any origin to make authenticated requests to your AdonisJS endpoints, potentially exposing Firestore operations that should be origin-restricted. You must secure CORS in AdonisJS and validate origins server-side to mitigate this risk.
What additional measures should I take when using a wildcard CORS policy in development?
Avoid using a wildcard (*) for allowedOrigins when credentials are enabled. In development, if you must use a wildcard for convenience, ensure endpoints do not expose sensitive Firestore operations and add server-side origin validation in AdonisJS to explicitly check the Origin header against a denylist or allowlist before proxying requests.