FastAPI validates request bodies through Pydantic by default, which removes a large class of problems before you write anything. What's left is mostly configuration and authorisation.
CORS
This combination came up a lot across the 24 builds we scanned. Set during development so something would render, then shipped as-is.
Browsers reject wildcard origins combined with credentials, so this often surfaces as a bug rather than a silent risk. Not always, though, and not for non-browser clients.
The docs
/docs and /redoc are enabled by default and describe every endpoint, parameter and schema you have. That's a map of your API.
Disabling docs_url alone leaves /openapi.json serving the same information. Disable all three.
Auth dependencies check identity, not ownership
Depends(current_user) confirms someone is authenticated. The query then returns whatever ID was asked for.
This was the most consequential pattern we found in that study. It's easy to miss in FastAPI specifically, because the dependency injection makes the endpoint look well-protected.
Response models
Returning an ORM object serialises whatever is on it, including columns you didn't intend to expose.
response_model filters the output to declared fields. Without it, a password hash on the model goes out with the response.
Raw SQL
SQLAlchemy's query builder parameterises. text() with an f-string doesn't:
The rest
Rate limiting isn't built in. slowapi or a reverse proxy. Set debug=False in production. Bound pagination parameters with Query(le=100) or someone will request every row. Security headers belong in middleware or the proxy in front.