Opened 3 years ago

Closed 3 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 Tomasz Wójcik)

In Django 4, #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).

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 = 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.

Change History (7)

comment:1 by Tomasz Wójcik, 3 years ago

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.

comment:2 by Tomasz Wójcik, 3 years ago

Description: modified (diff)

comment:3 by Tim Graham, 3 years ago

Summary: Add missing support for `Origin: null` (`CSRF_TRUSTED_ORIGINS`)Origin header checking fails for null origin
Type: UncategorizedBug

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

comment:4 by Tomasz Wójcik, 3 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.

Last edited 3 years ago by Tomasz Wójcik (previous) (diff)

comment:5 by Tomasz Wójcik, 3 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 Tomasz Wójcik, 3 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 Tomasz Wójcik, 3 years ago

Resolution: invalid
Status: newclosed
Note: See TracTickets for help on using tickets.
Back to Top