FastAPI 0.140.0-0.141.1 can expose the raw values wrapped by Pydantic’s Secret classes when a route returns a plain dictionary or list without a response model. The leak can reveal passwords, API keys, or any other credential a developer tried to hide.
Why the bug matters
FastAPI builds JSON responses by inspecting a view function’s return type. If you provide a response model, FastAPI hands the object to Pydantic, which masks SecretStr as "**********". In the affected versions, the framework only recognizes the built-in SecretStr type. When you subclass Secret (or use a custom secret type) and return the object inside a raw dict or list, FastAPI falls back to a generic object-to-dict conversion. That conversion reaches the private attribute that holds the actual secret value and sends it to the client unchanged.
The leakage happens only when all three conditions are met:
- The secret type subclasses Pydantic’s
Secretbase class. - The route does not declare a response model.
- The view returns the secret inside a plain
dictorlist.
How to protect your secrets today
- Declare a response model for every endpoint that may return data containing secrets. FastAPI will then let Pydantic handle serialization, which correctly masks the values.
- Wrap secrets inside a Pydantic
BaseModelfield instead of returning raw containers. The model’s field type can be a recognized secret class, ensuring proper handling. - Register a custom JSON encoder for your secret subclass if you must keep the current return style. The encoder can return the masked representation (
"**********").
Severity and community response
The issue is low severity. It requires a specific setup to trigger, but any accidental exposure of credentials is a risk, especially in public APIs or services that log responses.
Takeaway: Leaving out a response model can turn a well-intended secret wrapper into a data leak. Adding explicit response models or custom encoders is a cheap, reliable way to keep credentials hidden until FastAPI ships a built-in fix.
