Django 1.11 has a bug that causes intermittent CSRF validation failures
Over on Twitter, I said:
People say that Django version upgrades are easy and reliable. That is why our web app, moved from 1.10 to 1.11, is now throwing CSRF errors on *a single form* but only when 'DEBUG=False' which, you know, doesn't help debug the issue.
Last week I updated our Django web application from Django 1.10.7 to 1.11.22. Today, one of its users reported that when they tried to submit a form, the application reported:
Forbidden (403)
CSRF verification failed. Request aborted.More information is available with DEBUG=True.
At first I expected this to be a simple case of Django's CSRF
browser cookie
expiring or getting blocked. However, the person reproduced the
issue, and then I reproduced the issue too, except that when I
switched the live web app over to 'DEBUG=True
', it didn't happen,
and then sometimes it didn't happen even when debugging was off.
(Our application is infrequently used, so it's not surprising that this issue didn't surface (or didn't get reported) for a week.)
There are a number of reports of similar things on the Internet, for example here, here, here, and especially Django ticket #28488. Unfortunately not only was ticket 28488 theoretically fixed years ago, but it doesn't match what I see in Firefox's Network pane; there are no 404 HTTP requests served by our Django app, just regular successful ones.
(Here hints that maybe the issue involves using both sessions and CSRF cookies, which we do because sessions are a requirement for HTTP Basic Authentication, or at least they were at one point.)
The most popular workaround appears to be to stop Django from doing
CSRF checks, often by setting CSRF_TRUSTED_ORIGINS
to some value. My workaround for now is to revert back to Django
1.10.7; it may not be supported, but it actually works reliably for
us, unlike Django 1.11. I am not sure that we will ever try 1.11
again; an intermittent failure that only happens in production is
a really bad thing and not something I am very enthused about
risking.
(I'm not particularly happy about this state of affairs and I have low expectations for the Django people fixing this issue in the remaining lifetime of 1.11, since this has clearly been happening with 1.11 for some time. Since I'm not willing to run 1.11 in production to test and try things for the Django people, it doesn't seem particularly useful to even try to report a bug.)
|
|