Strict Content-Type Checking¶
Warning
This page hasn’t been translated into your language yet. 🌍
We’re currently switching to an automated translation system 🤖, which will help keep all translations complete and up to date.
Learn more: Contributing - Translations
By default, FastAPI uses strict Content-Type header checking for JSON request bodies, this means that JSON requests must include a valid Content-Type header (e.g. application/json) in order for the body to be parsed as JSON.
CSRF Risk¶
This default behavior provides protection against a class of Cross-Site Request Forgery (CSRF) attacks in a very specific scenario.
These attacks exploit the fact that browsers allow scripts to send requests without doing any CORS preflight check when they:
- don't have a
Content-Typeheader (e.g. usingfetch()with aBlobbody) - and don't send any authentication credentials.
This type of attack is mainly relevant when:
- the application is running locally (e.g. on
localhost) or in an internal network - and the application doesn't have any authentication, it expects that any request from the same network can be trusted.
Example Attack¶
Imagine you build a way to run a local AI agent.
It provides an API at
http://localhost:8000/v1/agents/multivac
There's also a frontend at
http://localhost:8000
Tip
Note that both have the same host.
Then using the frontend you can make the AI agent do things on your behalf.
As it's running locally, and not in the open internet, you decide to not have any authentication set up, just trusting the access to the local network.
Then one of your users could install it and run it locally.
Then they could open a malicious website, e.g. something like
https://evilhackers.example.com
And that malicious website sends requests using fetch() with a Blob body to the local API at
http://localhost:8000/v1/agents/multivac
Even though the host of the malicious website and the local app is different, the browser won't trigger a CORS preflight request because:
- It's running without any authentication, it doesn't have to send any credentials.
- The browser thinks it's not sending JSON (because of the missing
Content-Typeheader).
Then the malicious website could make the local AI agent send angry messages to the user's ex-boss... or worse. 😅
Open Internet¶
If your app is in the open internet, you wouldn't "trust the network" and let anyone send privileged requests without authentication.
Attackers could simply run a script to send requests to your API, no need for browser interaction, so you are probably already securing any privileged endpoints.
In that case this attack / risk doesn't apply to you.
This risk and attack is mainly relevant when the app runs on the local network and that is the only assumed protection.
Allowing Requests Without Content-Type¶
If you need to support clients that don't send a Content-Type header, you can disable strict checking by setting strict_content_type=False:
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI(strict_content_type=False)
class Item(BaseModel):
name: str
price: float
@app.post("/items/")
async def create_item(item: Item):
return item
With this setting, requests without a Content-Type header will have their body parsed as JSON, which is the same behavior as older versions of FastAPI.
Info
This behavior and configuration was added in FastAPI 0.132.0.