Recommend Warning and Safer Defaults for url_for(..., _external=True)
Hi Flask team,
We recently analyzed several Flask-based applications and noticed a recurring security concern related to url_for(..., _external=True) when used in untrusted request contexts. Specifically, since it uses request.host by default to construct the external URL, applications that do not explicitly configure SERVER_NAME or sanitize headers can be vulnerable to host header injection.
To improve developer awareness and reduce misuse, we suggest: Add a warning to the url_for documentation about the risk of relying on request.host, and recommend the use of SERVER_NAME or trusted_hosts when generating external URLs.
We’d be happy to help draft the relevant documentation or contribute a pull request if this direction aligns with the maintainers' goals.
Best regards, Rui Yang and Zhengyu Liu Johns Hopkins University
This is already documented in Deploying: https://flask.palletsprojects.com/en/stable/deploying/proxy_fix/
FWIW this is only a problem when all these criteria are met:
- the URL is used externally, and in a context where the recipient of the email may be someone else than the person making the request with the bogus Host header (password reset emails are particularly "interesting" there)
- requests with an incorrect Host header actually reach the webapp (in most production deployments that's probably not the case) and are handled by it
@davidism I'm not sure if just mentioning ProxyFix is sufficient - you can have a simple deployment using nginx+uwsgi without any proxies/LBs involved, and depending on the nginx config you may be vulnerable.
A section about SERVER_NAME and TRUSTED_HOSTS on the security docs page would probably be appropriate https://flask.palletsprojects.com/en/stable/web-security/. Happy to review a PR.
Hi, I’m new to open source and would like to work on this issue. Can I take it?
Thanks for the contribution and this looks great! I appreciate the clean and thoughtful write-up.
Glad to see the issue addressed this thoroughly. Let me know if I can help further.