Unrestricted Resource Consumption

How to Fix Unrestricted Resource Consumption in FastAPI March 2026 [CVE-2021-32677]

[Updated March 2026] Updated CVE-2021-32677

Overview

The CVE-2021-32677 case shows how FastAPI versions < 0.65.2 could mis-handle incoming requests by reading the request payload as JSON even when the Content-Type header was not a JSON type. This could enable CSRF attacks in cookies-based auth scenarios and, more broadly, lead to Unrestricted Resource Consumption because an attacker can prompt the server to parse large or crafted payloads that aren’t actually JSON, consuming CPU and memory. In practice, a browser could submit a request with content-type text/plain containing JSON data, which FastAPI would still attempt to parse as JSON. Since text/plain requests are not always subjected to CORS preflight, the browser could send authenticated requests (with cookies) without triggering the normal CSRF safeguards. This vulnerability was fixed in FastAPI 0.65.2, which only parses JSON when the content-type is application/json or other JSON-compatible media types (e.g., application/geo+json). The Unrestricted Resource Consumption risk here arises from parsing and processing potentially large or crafted payloads under conditions where the request should have been rejected early due to an incorrect content-type.

Affected Versions

< 0.65.2

Code Fix Example

FastAPI API Security Remediation
Vulnerable:
from fastapi import FastAPI, Request

app = FastAPI()

@app.post('/data')
async def data(req: Request):
    payload = await req.json()  # this would parse JSON even if content-type isn't application/json
    # process payload
    return {'ok': True}

# Fixed:
from fastapi import FastAPI, Request, HTTPException
from fastapi.responses import JSONResponse

app = FastAPI()

def is_json_content_type(req: Request) -> bool:
    ct = (req.headers.get('content-type') or '').lower()
    return ct.startswith('application/json') or '+json' in ct


@app.post('/data')
async def data_fixed(req: Request):
    if not is_json_content_type(req):
        raise HTTPException(status_code=415, detail='Unsupported Media Type')
    payload = await req.json()  # safe to parse now that content-type is JSON
    # process payload
    return {'ok': True}

CVE References

Choose which optional cookies to allow. You can change this any time.