Configuring trusted hosts
Whenever Expanse needs to generate absolute URLs, it uses the Host header from the incoming request. However, this header can be easily manipulated by an attacker by relying on inconsistencies in how different software (web servers, reverse proxies, web frameworks, etc.) handle it.
You can learn more about Host header attacks by reading this article.
To mitigate this risk, Expanse allows you to define a list of hosts that your application will trust. Everytime
Expanse needs to use the Host header, it will check the host against this list and raise a SuspiciousOperationError if
it's not on the list.
You can configure the trusted hosts by setting the HTTP_TRUSTED_HOSTS environment variable in your .env file.
This variable should contain a comma-separated list of hosts that your application will trust.
HTTP_TRUSTED_HOSTS=example.com,www.example.com
You can trust a root domain and all its subdomains by prefixing the domain with a dot (.):
HTTP_TRUSTED_HOSTS=.example.com
If, instead, you want to trust all hosts (not recommended), you can set the variable to an asterisk (*):
HTTP_TRUSTED_HOSTS=*
During development, Expanse will automatically trust the localhost, 127.0.0.1 and ::1 hosts, so you don't need
to add them to the HTTP_TRUSTED_HOSTS setting.
Trusting hosts manually
If you need an advanced configuration, or a custom logic to determine which hosts should be trusted, you should first
remove the TrustHosts middleware from your middleware stack:
from expanse.core.http.middleware.middleware_stack import MiddlewareStack
from expanse.http.middleware.trust_host import TrustHosts
async def configure_middleware(stack: MiddlewareStack) -> None:
stack.remove(TrustHosts)
Then, you can create your own middleware to implement the logic you need:
class CustomTrustHosts:
async def handle(self, request: Request, call_next: RequestHandler) -> Response:
trusted_host = ... # Your custom logic to get the trusted hosts
request.set_trusted_hosts(trusted_host)
response = await call_next(request)
return response
Finally, add your custom middleware to the middleware stack:
from expanse.core.http.middleware.middleware_stack import MiddlewareStack
async def configure_middleware(stack: MiddlewareStack) -> None:
stack.remove(TrustHosts).add(CustomTrustHosts)