CVE-2021-32677

8.2 HIGH

📋 TL;DR

FastAPI versions below 0.65.2 are vulnerable to CSRF attacks when using cookie-based authentication with JSON payloads. The vulnerability allows attackers to bypass CORS protections by sending requests with text/plain content-type containing JSON data, which FastAPI incorrectly parses. This affects any FastAPI application using cookie authentication that accepts JSON payloads.

💻 Affected Systems

Products:
  • FastAPI
Versions: All versions below 0.65.2
Operating Systems: All
Default Config Vulnerable: ⚠️ Yes
Notes: Only affects applications using cookie-based authentication with JSON payload endpoints. Applications using token-based authentication (Bearer tokens) are not affected.

📦 What is this software?

⚠️ Risk & Real-World Impact

🔴

Worst Case

Attackers can perform unauthorized actions on behalf of authenticated users, potentially leading to data theft, account takeover, or system compromise.

🟠

Likely Case

Unauthorized API calls leading to data manipulation, privilege escalation, or information disclosure.

🟢

If Mitigated

Limited impact with proper CSRF tokens, same-origin policies, or content-type validation in place.

🌐 Internet-Facing: HIGH
🏢 Internal Only: MEDIUM

🎯 Exploit Status

Public PoC: ⚠️ Yes
Weaponized: LIKELY
Unauthenticated Exploit: ✅ No
Complexity: LOW

Exploitation requires the victim to be authenticated and visit a malicious site. The attack leverages browser behavior with text/plain content-type to bypass CORS preflight checks.

🛠️ Fix & Mitigation

✅ Official Fix

Patch Version: 0.65.2

Vendor Advisory: https://github.com/tiangolo/fastapi/security/advisories/GHSA-8h2j-cgx8-6xv7

Restart Required: Yes

Instructions:

1. Update FastAPI: pip install fastapi==0.65.2 or higher
2. Restart your FastAPI application
3. Verify the update with: pip show fastapi

🔧 Temporary Workarounds

Content-Type Validation Middleware

all

Add middleware to reject requests with non-JSON content-type headers before JSON parsing occurs.

from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
from starlette.middleware.base import BaseHTTPMiddleware

class ContentTypeMiddleware(BaseHTTPMiddleware):
    async def dispatch(self, request: Request, call_next):
        content_type = request.headers.get('content-type', '')
        if request.method in ['POST', 'PUT', 'PATCH'] and 'application/json' not in content_type and 'application/geo+json' not in content_type:
            return JSONResponse(status_code=415, content={'detail': 'Unsupported Media Type'})
        return await call_next(request)

app = FastAPI()
app.add_middleware(ContentTypeMiddleware)

🧯 If You Can't Patch

  • Implement CSRF tokens for all state-changing endpoints
  • Use token-based authentication (Bearer tokens) instead of cookie-based authentication

🔍 How to Verify

Check if Vulnerable:

Check FastAPI version: pip show fastapi | grep Version. If version is below 0.65.2 and application uses cookie authentication with JSON endpoints, it's vulnerable.

Check Version:

pip show fastapi | grep Version

Verify Fix Applied:

After updating to 0.65.2+, test that requests with text/plain content-type containing JSON are rejected with 415 status code.

📡 Detection & Monitoring

Log Indicators:

  • 415 Unsupported Media Type errors for text/plain requests to JSON endpoints
  • Unexpected successful JSON parsing with non-JSON content-type headers

Network Indicators:

  • POST/PUT/PATCH requests with text/plain content-type to JSON endpoints
  • Cross-origin requests with cookie authentication

SIEM Query:

content_type:"text/plain" AND (method:POST OR method:PUT OR method:PATCH) AND status:200 AND path:"/api/*"

🔗 References

📤 Share & Export