#33360: Add missing support for `Origin: null` (`CSRF_TRUSTED_ORIGINS`)
-------------------------------------+-------------------------------------
Reporter: Tomasz | Owner: nobody
Wójcik |
Type: | Status: new
Uncategorized |
Component: CSRF | Version: 4.0
Severity: Normal | Keywords:
Triage Stage: | origin,CSRF_TRUSTED_ORIGINS,null
Unreviewed | Has patch: 0
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-------------------------------------+-------------------------------------
In Django 4, [https://code.djangoproject.com/ticket/16010 #16010] has been
released. It includes 2 changes that affect my project:
- origins in `CSRF_TRUSTED_ORIGINS` are required to include an HTTP scheme
- `Origin` header, if present in the request headers, will always be
checked against `CSRF_TRUSTED_ORIGINS`
The problem is that by default when the project is running on localhost,
browsers will always send `Origin: null` (correct me if I'm wrong).
[https://github.com/django/django/blob/2f73e5406d54cb8945e187eff302a3a3373350be/django/middleware/csrf.py#L433
if 'HTTP_ORIGIN' in request.META] will always evaluate to `True` on
localhost, even if `Origin: null`.
[https://github.com/django/django/blob/2f73e5406d54cb8945e187eff302a3a3373350be/django/middleware/csrf.py#L281
if request_origin in self.allowed_origins_exact] will never evaluate to
`True` on localhost, as `null` will never be a valid origin as it doesn't
include a scheme.
As a result, it's impossible to POST a form on localhost.
------------------------
- If it's a regression to 16010, I'd propose changing
[https://github.com/django/django/blob/2f73e5406d54cb8945e187eff302a3a3373350be/django/middleware/csrf.py#L433
if 'HTTP_ORIGIN' in request.META]
to
`if request.META.get('HTTP_ORIGIN') is not None`
- If it's a feature, I'd suggest adding the above or a setting
`CSRF_ALLOW_NULL_ORIGIN = False` but it'd require a change in all projects
migrating to v 4
- if I am mistaken and the `Origin` header should be automatically
populated by browsers with a non-null value when POSTing from localhost,
this ticket can be closed (or maybe docs could be improved?)
-----------------------
Sample code that is failing on 4 and is working fine on 3.x
{{{
# settings
from corsheaders.defaults import default_headers
CORS_ALLOWED_ORIGINS = [
"http://localhost:8000",
"http://127.0.0.1:8000",
]
CSRF_TRUSTED_ORIGINS = [
"http://localhost:8000",
"http://127.0.0.1:8000",
]
}}}
{{{
# template
<form method="post">
{% csrf_token %}
</form>
}}}
Error:
> Origin checking failed - null does not match any trusted origins.
Request headers:
{{{
Host: localhost:8000
Origin: null
}}}
Even if I'm wrong, it's worth noting that the standard defines `opaque
origin` when `Origin` will be set to `null` so technically this value
should be supported anyway but I don't understand its definition.
Let me know if there's something to do here. If yes, please assign me.
--
Ticket URL: <https://code.djangoproject.com/ticket/33360>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/052.c20dc9af1127eb0a2ca6aa6653a75618%40djangoproject.com.