Opened 4 years ago
Closed 4 years ago
#33360 closed Bug (invalid)
Origin header checking fails for null origin
| Reported by: | Tomasz Wójcik | Owned by: | nobody |
|---|---|---|---|
| Component: | CSRF | Version: | 4.0 |
| Severity: | Normal | Keywords: | origin, CSRF_TRUSTED_ORIGINS, null |
| Cc: | Triage Stage: | Unreviewed | |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description (last modified by )
In Django 4, #16010 has been released. It includes 2 changes that affect my project:
- origins in
CSRF_TRUSTED_ORIGINSare required to include an HTTP scheme Originheader, if present in the request headers, will always be checked againstCSRF_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).
if 'HTTP_ORIGIN' in request.META will always evaluate to True on localhost, even if Origin: null.
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
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 = Falsebut it'd require a change in all projects migrating to v 4
- if I am mistaken and the
Originheader 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 (opaque origin) definition.
Let me know if there's something to do here. If yes, please assign me.
Change History (7)
comment:1 by , 4 years ago
comment:2 by , 4 years ago
| Description: | modified (diff) |
|---|
comment:3 by , 4 years ago
| Summary: | Add missing support for `Origin: null` (`CSRF_TRUSTED_ORIGINS`) → Origin header checking fails for null origin |
|---|---|
| Type: | Uncategorized → Bug |
What browser do you see a null origin? On Firefox and Chrome, I see http://localhost:8000.
comment:4 by , 4 years ago
Chrome 95.0.4638.54 (Official Build) (64-bit) and Firefox 93.0 (64-bit), Mint (Ubuntu), dockerized env. I find it surprising that no one else run into his issue earlier - maybe it's just a matter of my setup.
comment:5 by , 4 years ago
I'm trying to reproduce in the new minimal repro and also getting the origin header. I will let you know once I figure out how to reproduce it.
comment:6 by , 4 years ago
Oh my... I had
<meta name="referrer" content="no-referrer">
in my base template. Sorry for the problem. Please close it.
comment:7 by , 4 years ago
| Resolution: | → invalid |
|---|---|
| Status: | new → closed |
I don't think I have the power to summon someone, but in 16010 Adam Johnson has been CCed and he once wrote
browsers send `Origin: null` for localhost/127.0.0.1
(I will try anyway): CC Adam Johnson please confirm if it still holds true.