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 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 |
Frequently Asked Questions
Can Firestore security rules alone prevent issues caused by a CORS wildcard in AdonisJS?
What additional measures should I take when using a wildcard CORS policy in development?
*) 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.