[Django] #33360: Add missing support for `Origin: null` (`CSRF_TRUSTED_ORIGINS`)

260 views
Skip to first unread message

Django

unread,
Dec 12, 2021, 3:34:33 PM12/12/21
to django-...@googlegroups.com
#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.

Django

unread,
Dec 12, 2021, 3:46:21 PM12/12/21
to django-...@googlegroups.com
#33360: Add missing support for `Origin: null` (`CSRF_TRUSTED_ORIGINS`)
-------------------------------------+-------------------------------------
Reporter: Tomasz Wójcik | Owner: nobody
Type: Uncategorized | Status: new
Component: CSRF | Version: 4.0
Severity: Normal | Resolution:

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
-------------------------------------+-------------------------------------

Comment (by Tomasz Wójcik):

I don't think I have the power to summon someone, but in 16010 Adam
Johnson has been CCed and he once wrote

[https://github.com/adamchainz/django-cors-
headers/issues/241#issuecomment-315537226 browsers send `Origin: null` for
localhost/127.0.0.1]

(I will try anyway): CC Adam Johnson please confirm if it still holds
true.

--
Ticket URL: <https://code.djangoproject.com/ticket/33360#comment:1>

Django

unread,
Dec 12, 2021, 3:48:44 PM12/12/21
to django-...@googlegroups.com
#33360: Add missing support for `Origin: null` (`CSRF_TRUSTED_ORIGINS`)
-------------------------------------+-------------------------------------
Reporter: Tomasz Wójcik | Owner: nobody
Type: Uncategorized | Status: new
Component: CSRF | Version: 4.0
Severity: Normal | Resolution:

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
-------------------------------------+-------------------------------------
Description changed by Tomasz Wójcik:

Old description:

New description:

------------------------

to

-----------------------

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.

--

--
Ticket URL: <https://code.djangoproject.com/ticket/33360#comment:2>

Django

unread,
Dec 12, 2021, 4:28:06 PM12/12/21
to django-...@googlegroups.com
#33360: Origin header checking fails for null origin

-------------------------------------+-------------------------------------
Reporter: Tomasz Wójcik | Owner: nobody
Type: Bug | Status: new
Component: CSRF | Version: 4.0
Severity: Normal | Resolution:

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
-------------------------------------+-------------------------------------
Changes (by Tim Graham):

* type: Uncategorized => Bug


Comment:

What browser do you see a null origin? On Firefox and Chrome, I see
`http://localhost:8000`.

--
Ticket URL: <https://code.djangoproject.com/ticket/33360#comment:3>

Django

unread,
Dec 12, 2021, 4:38:27 PM12/12/21
to django-...@googlegroups.com
#33360: Origin header checking fails for null origin
-------------------------------------+-------------------------------------
Reporter: Tomasz Wójcik | Owner: nobody
Type: Bug | Status: new
Component: CSRF | Version: 4.0
Severity: Normal | Resolution:

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
-------------------------------------+-------------------------------------

Comment (by Tomasz Wójcik):

Chrome 95.0.4638.54 (Official Build) (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.

--
Ticket URL: <https://code.djangoproject.com/ticket/33360#comment:4>

Django

unread,
Dec 12, 2021, 5:07:27 PM12/12/21
to django-...@googlegroups.com
#33360: Origin header checking fails for null origin
-------------------------------------+-------------------------------------
Reporter: Tomasz Wójcik | Owner: nobody
Type: Bug | Status: new
Component: CSRF | Version: 4.0
Severity: Normal | Resolution:

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
-------------------------------------+-------------------------------------

Comment (by Tomasz Wójcik):

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.

--
Ticket URL: <https://code.djangoproject.com/ticket/33360#comment:5>

Django

unread,
Dec 12, 2021, 5:38:27 PM12/12/21
to django-...@googlegroups.com
#33360: Origin header checking fails for null origin
-------------------------------------+-------------------------------------
Reporter: Tomasz Wójcik | Owner: nobody
Type: Bug | Status: new
Component: CSRF | Version: 4.0
Severity: Normal | Resolution:

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
-------------------------------------+-------------------------------------

Comment (by Tomasz Wójcik):

Oh my... I had

{{{
<meta name="referrer" content="no-referrer">
}}}

in my base template. Sorry for the problem. Please close it.

--
Ticket URL: <https://code.djangoproject.com/ticket/33360#comment:6>

Django

unread,
Dec 12, 2021, 5:42:35 PM12/12/21
to django-...@googlegroups.com
#33360: Origin header checking fails for null origin
-------------------------------------+-------------------------------------
Reporter: Tomasz Wójcik | Owner: nobody
Type: Bug | Status: closed
Component: CSRF | Version: 4.0
Severity: Normal | Resolution: invalid

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
-------------------------------------+-------------------------------------
Changes (by Tomasz Wójcik):

* status: new => closed
* resolution: => invalid


--
Ticket URL: <https://code.djangoproject.com/ticket/33360#comment:7>

Reply all
Reply to author
Forward
0 new messages