HIGH cross site request forgeryfastapifirestore

Cross Site Request Forgery in Fastapi with Firestore

Cross Site Request Forgery in Fastapi with Firestore — how this specific combination creates or exposes the vulnerability

Cross Site Request Forgery (CSRF) in a FastAPI application that uses Google Cloud Firestore arises when state-changing operations rely on cookies or session tokens for authentication while lacking anti-CSRF protections. FastAPI does not enforce CSRF mitigation by default, and if endpoints assume requests originate only from your frontend (e.g., browser JavaScript), forged requests from attacker-controlled sites can succeed.

When Firestore is used as the backend datastore, the risk centers on how authentication and authorization are enforced. If your FastAPI service uses session cookies or an identity provider that issues cookies, and those cookies are automatically included by browsers on cross-origin requests, an attacker can craft forms or scripts on their own site that invoke your FastAPI endpoints. Because Firestore security rules typically enforce identity at the database level (e.g., via Firebase Authentication UID rules), the authorization decision may appear correct in logs, but the request itself was initiated without user intent.

Consider a FastAPI endpoint that updates a Firestore document representing a user profile. If the endpoint reads the UID from an authenticated session cookie and directly applies the update to Firestore based on request JSON, a forged request from another site can perform unwanted changes. For example, an attacker can trick a victim into submitting a form that calls /api/profile with modified data. Firestore rules may allow the write because the UID matches, but the operation was not intentionally initiated by the user. The unauthenticated attack surface is expanded if your API also exposes endpoints that rely on CORS configurations that are too permissive or if preflight checks are not strict, enabling cross-origin credentialed requests.

Additionally, if your FastAPI routes serve both API and static assets, or if cookie attributes like SameSite are not set strictly, browsers may include authentication cookies in cross-site requests. Firestore’s UID-based rules do not protect against CSRF at the API layer; they only enforce data-level permissions once the request reaches Firestore. Therefore, CSRF in this stack manifests as a lack of origin validation and missing synchronization tokens (e.g., anti-CSRF tokens or SameSite cookies) around mutating endpoints, even when Firestore rules are correctly scoped.

Firestore-Specific Remediation in Fastapi — concrete code fixes

To mitigate CSRF for FastAPI endpoints that interact with Firestore, enforce strict origin and credential handling, and use anti-CSRF tokens for state-changing operations. The following patterns assume you use Firebase Admin SDK or a Firestore client library to access Firestore securely within FastAPI routes.

1. Set strict CORS and cookie attributes

Ensure CORS middleware only allows trusted origins and does not expose credentials to untrusted domains. Configure cookies with SameSite=Lax (or Strict for sensitive actions) and Secure.

from fastapi import FastAPI, Response
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()
app.add_middleware(
    CORSMiddleware,
    allow_origins=["https://your-trusted-frontend.com"],
    allow_credentials=True,
    allow_methods=["GET", "POST"],
    allow_headers=["Authorization", "Content-Type"],
)

@app.post("/api/profile")
async def update_profile(response: Response):
    response.set_cookie(
        key="session_id",
        value="...",
        httponly=True,
        secure=True,
        samesite="Lax",
    )
    return {"status": "ok"}

2. Use anti-CSRF tokens for mutating endpoints

Generate and validate per-request or per-session CSRF tokens for POST, PUT, PATCH, and DELETE routes. Store the token server-side (e.g., in session data) and require it in a header or form field. Below is an example using a simple token stored in a secure cookie and validated on each mutation.

import secrets
from fastapi import FastAPI, Request, Cookie, HTTPException
from fastapi.responses import JSONResponse

app = FastAPI()

def generate_csrf_token() -> str:
    return secrets.token_urlsafe(32)

@app.post("/api/firestore/update")
async def update_firestore(
    request: Request,
    csrf_token: str = Cookie(None),
    x_csrf_token: str | None = Header(None),
):
    if not csrf_token or csrf_token != x_csrf_token:
        raise HTTPException(status_code=403, detail="Invalid or missing CSRF token")
    # Proceed to interact with Firestore safely
    # Example Firestore write using the Firebase Admin SDK client initialized elsewhere
    # from firebase_admin import firestore
    # db = firestore.client()
    # db.collection("items").document(doc_id).update({...})
    return JSONResponse(content={"message": "updated"})

3. Validate Origin and Referer headers cautiously

For endpoints that do not rely on cookies for authentication (e.g., token-based), you can additionally validate the Origin or Referer header as a secondary defense. However, do not rely on this alone, as these headers can be omitted in some scenarios.

from fastapi import FastAPI, Request, HTTPException

app = FastAPI()

@app.post("/api/order/create")
async def create_order(request: Request):
    origin = request.headers.get("origin")
    referer = request.headers.get("referer")
    allowed = {"https://your-trusted-frontend.com"}
    if origin not in allowed or referer not in allowed:
        raise HTTPException(status_code=403, detail="Invalid request origin")
    # Continue with Firestore transaction
    return {"order_id": "generated"}

4. Follow principle of least privilege in Firestore rules

Ensure Firestore security rules are scoped to the minimal required resources and UID. While this does not prevent CSRF at the API layer, it limits the impact of a successful forged request.

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

Frequently Asked Questions

Does Firestore security rules prevent CSRF in FastAPI?
No. Firestore rules enforce data-level permissions based on UID, but they do not prevent cross-origin requests from triggering writes. CSRF protection must be implemented at the API layer in FastAPI using anti-CSRF tokens, strict CORS, and secure cookie attributes.
Can SameSite cookies alone stop CSRF for Firestore-backed FastAPI endpoints?
SameSite cookies reduce the risk of CSRF by limiting when cookies are sent with cross-site requests, but they are not a complete defense. Use them together with anti-CSRF tokens and strict CORS policies for robust protection.