﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
33360	Origin header checking fails for null origin	Tomasz Wójcik	nobody	"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 (`opaque origin`) definition.
Let me know if there's something to do here. If yes, please assign me.
"	Bug	closed	CSRF	4.0	Normal	invalid	origin,CSRF_TRUSTED_ORIGINS,null		Unreviewed	0	0	0	0	0	0
