Harden `django.shortcuts.redirect` to validate redirect URL
- Dominant language
- No language data
- Stars
- 188
- Forks
- 7
- PR merge metrics
- No merged PRs in 30d
Description
### Code of Conduct
- [x] I agree to follow Django's Code of Conduct
### Feature Description
I suggest extending the `redirect` shortcut with a few additional (opt-in) arguments to validate the URL being redirected to. Notably:
- `allowed_hosts`, to specify hosts that the URL can be redirected to (or `[]` to require only a path-based redirect)
- `require_https`, to ensure the redirect stays secure
Following that validation, `iri_to_uri` would be run on the path to ensure it's correctly encoded before being passed to the response.
### Problem
Following [a conversation on the forum](https://forum.djangoproject.com/t/why-is-the-use-of-url-has-allowed-host-and-scheme-discouraged/35314), it was noted that Django's `url_has_allowed_host_and_scheme` is an internal API, despite being a core piece of functionality when validating a user's redirect API (eg the `next` query param).
```python
def my_view(request):
next_url = request.GET.get('next')
if next_url and url_has_allowed_host_and_scheme(next_url, allowed_hosts=["example.com"], require_https=request.is_secure()):
return redirect(next_url)
return redirect("/")
```
I believe this pattern performs all the validation, however it's easy to mess up:
- `url_has_allowed_host_and_scheme` isn't publicly documented, therefore has no stability guarantees (sort of)
- Someone could easily skip `redirect` and just build a `HttpResponse` and set a `Location` header on it (unlikely, but probably happens)
- People may forget that it's possible redirect `https` -> `http`.
### Request or proposal
proposal
### Additional Details
As Carlton correctly points out on the forum thread, validation is multi-step, and you need **all of them** to pass. That's why I don't think making `url_has_allowed_host_and_scheme` public is necessarily the right solution. Instead, a single public API ensures all steps of the validation are performed, so one can't be missed or forgotten.
### Implementation Suggestions
Many of the building blocks are already there in `url_has_allowed_host_and_scheme`, they just need to be used.
If not passed, the validation should not be applied, so as not to be a breaking change to `redirect`.
---
These thoughts are my own, and not necessarily of the wider Security Team.
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.