HIGH cross site request forgeryfastapi

Cross Site Request Forgery in Fastapi

How Cross Site Request Forgery Manifests in Fastapi

Cross Site Request Forgery (CSRF) in Fastapi applications exploits the fact that browsers automatically include cookies and authentication headers when making requests to a domain. An attacker crafts a malicious website that, when visited by an authenticated user, triggers unwanted actions on the Fastapi backend without the user's knowledge or consent.

Consider a Fastapi endpoint that processes payments:

from fastapi import FastAPI, Form, Request

app = FastAPI()

@app.post("/transfer")
async def transfer_funds(
    request: Request,
    from_account: str = Form(...),
    to_account: str = Form(...),
    amount: float = Form(...)
):
    # No CSRF protection
    # Process transfer logic here
    return {"status": "success"}

An attacker could create a malicious page that automatically submits this form:

<form id="csrf-form" action="https://your-fastapi-app.com/transfer" method="POST" style="display:none;">
    <input type="hidden" name="from_account" value="victim-account">
    <input type="hidden" name="to_account" value="attacker-account">
    <input type="hidden" name="amount" value="1000">
</form>
<script>document.getElementById('csrf-form').submit();</script>

When an authenticated user visits this page, their browser automatically sends cookies and any stored authentication tokens to the Fastapi backend, causing the unauthorized transfer to execute.

Fastapi's async nature doesn't prevent CSRF attacks. The vulnerability exists in the authentication mechanism and endpoint design, not in the framework's concurrency model. Any endpoint that performs state-changing operations without CSRF protection is vulnerable, regardless of whether it uses synchronous or asynchronous code.

Common Fastapi CSRF targets include:

  • Payment processing endpoints
  • User account modifications (email, password changes)
  • Administrative actions (user deletion, role changes)
  • Financial transactions (transfers, deposits, withdrawals)
  • Configuration changes

The risk is particularly high in Fastapi applications that rely solely on session cookies or JWT tokens stored in cookies, as these are automatically included in cross-origin requests by browsers.

Fastapi-Specific Detection

Detecting CSRF vulnerabilities in Fastapi requires both manual code review and automated scanning. middleBrick's black-box scanning approach is particularly effective for Fastapi applications since it tests the actual runtime behavior without requiring source code access.

middleBrick scans Fastapi endpoints for CSRF vulnerabilities by:

  1. Identifying state-changing HTTP methods (POST, PUT, PATCH, DELETE) that lack anti-CSRF tokens
  2. Testing for cookie-based authentication patterns
  3. Checking for missing SameSite cookie attributes
  4. Verifying the presence of CSRF middleware or protection mechanisms

The scanner tests each endpoint by attempting to submit requests with forged origins and examining the server's response. For Fastapi applications, middleBrick specifically looks for:

{
  "csrf_vulnerabilities": {
    "endpoint": "/api/transfer",
    "method": "POST",
    "risk_level": "high",
    "evidence": "No anti-CSRF token found, accepts requests from any origin",
    "recommendation": "Implement CSRF protection using Fastapi's middleware or add SameSite cookie attributes"
  }
}

middleBrick's scanning process takes 5-15 seconds and provides a security risk score (A-F) with specific findings for each vulnerability category. The tool tests the unauthenticated attack surface, making it ideal for identifying CSRF vulnerabilities that could be exploited by external attackers.

For manual detection in Fastapi codebases, look for these patterns:

# Vulnerable pattern - no CSRF protection
@app.post("/sensitive-action")
async def sensitive_action(
    request: Request,
    data: dict = Form(...)
):
    # Process sensitive action without verification
    return {"result": "processed"}

middleBrick's GitHub Action integration allows you to automatically scan Fastapi APIs in your CI/CD pipeline, failing builds if CSRF vulnerabilities are detected before deployment to production.

Fastapi-Specific Remediation

Fastapi provides several approaches to mitigate CSRF vulnerabilities. The most effective solution combines anti-CSRF tokens with proper cookie configuration.

Using Fastapi's built-in middleware for CSRF protection:

from fastapi import FastAPI, Request, Form, Depends
from fastapi.middleware import Middleware
from fastapi.middleware.csrf import CSRFMiddleware

app = FastAPI(middleware=[
    Middleware(CSRFMiddleware)
])

@app.post("/protected-endpoint")
async def protected_endpoint(
    csrf_token: str = Depends(CSRFMiddleware.csrf_cookie)
):
    # CSRF token is automatically validated
    return {"status": "protected"}

For applications using JWT tokens stored in cookies, implement SameSite attributes:

from fastapi import FastAPI, Response
from datetime import datetime, timedelta
import jwt

app = FastAPI()

SECRET_KEY = "your-secret-key"

async def create_jwt_token(response: Response, user_id: str):
    expire = datetime.utcnow() + timedelta(hours=1)
    token = jwt.encode({
        "sub": user_id,
        "exp": expire
    }, SECRET_KEY, algorithm="HS256")
    
    response.set_cookie(
        key="access_token",
        value=token,
        httponly=True,
        samesite="Strict",  # Prevents CSRF
        max_age=3600
    )

Alternative approach using double-submit cookie pattern:

from fastapi import FastAPI, Request, Form, Depends
from fastapi.middleware import Middleware
from fastapi.middleware.csrf import CSRFMiddleware
import secrets
import hashlib

app = FastAPI(middleware=[Middleware(CSRFMiddleware)])

async def get_csrf_token(request: Request):
    token = request.state.get("csrf_token")
    if not token:
        token = secrets.token_urlsafe(32)
        request.state.csrf_token = token
    return token

@app.post("/transfer")
async def transfer_funds(
    csrf_token: str = Depends(get_csrf_token),
    from_account: str = Form(...),
    to_account: str = Form(...),
    amount: float = Form(...)
):
    # Verify CSRF token matches cookie
    if request.cookies.get("csrf_token") != csrf_token:
        raise HTTPException(status_code=403, detail="CSRF token mismatch")
    
    # Process transfer
    return {"status": "transfer processed"}

For API-only Fastapi applications using JWT in Authorization headers, CSRF risk is minimal since browsers don't automatically include these headers in cross-origin requests. However, if you're using cookie-based authentication for your Fastapi API, implement one of the above protections.

middleBrick's continuous monitoring in the Pro plan can alert you if CSRF protections are accidentally removed during code changes, ensuring your Fastapi application remains secure over time.

Frequently Asked Questions

Does Fastapi's async nature make it more vulnerable to CSRF attacks?
No, Fastapi's async/await syntax doesn't affect CSRF vulnerability. CSRF exploits browser behavior and authentication mechanisms, not the concurrency model. Whether your Fastapi endpoints are synchronous or asynchronous, they're equally vulnerable if they lack proper CSRF protection. The vulnerability exists in how authentication tokens are handled, not in how Fastapi processes requests.
Can I use Fastapi's built-in CSRF middleware with all authentication methods?
Fastapi's CSRF middleware works best with cookie-based authentication. It's designed to generate and validate CSRF tokens that are stored in cookies and submitted with forms. If you're using JWT tokens in Authorization headers, the CSRF risk is already minimal since browsers don't automatically include these headers in cross-origin requests. For mixed authentication scenarios, you may need custom CSRF protection logic or rely on SameSite cookie attributes instead.