SimpleCookies are not correctly serialized with the file or database cache backends
|Reported by:||Raphael Kubo da Costa||Owned by:||Paul McMillan|
|Component:||Core (Cache system)||Version:||1.2|
|Cc:||Raphael Kubo da Costa, teolicy||Triage Stage:||Accepted|
|Has patch:||no||Needs documentation:||no|
|Needs tests:||yes||Patch needs improvement:||no|
As discussed in the django-developers mailing list, it appears that SimpleCookies in HttpResponses are not being correctly serialized when one uses either the file or the database cache backends.
The following steps are enough to trigger the incorrect behaviour:
- Enable UpdateCacheMiddleware and FetchFromCacheMiddleware in settings.py, and set CACHE_BACKEND accordingly
- Enable SessionMiddleware and CsrfViewMiddleware
- Have a view with a simple form and no specific cache decorators. Since the session application is being used, the
Vary: Cookieheader will be added anyway.
- In the template used by the view, include the
csrf_tokentag, as usual.
- Access the view, either via curl or a web browser.
- The first time the view is accessed, the csrf token is both set in the header as a cookie and displayed as a hidden form element, as expected. The header has the format
Set-Cookie: csrftoken=XX; Max-Age: YY; Path=/.
- The next times the view is accessed, the cookie header has the format
Set-Cookie: csrftoken="Set-Cookie: csrftoken=XX Max-Age: YY; Path=/", and so has the csrf form element, which causes the submitted form to be invalid when the csrf checks are made.
It turns out that
UpdateCacheMiddleware serializes the returned HttpResponse in
process_response, and both the file and the database cache backends use
pickle.dumps with protocol=pickle.HIGHEST_PROTOCOL. It is known that SimpleCookies are incompatible with pickle.HIGHEST_PROTOCOL. FetchFromCacheMiddleware later retrieves this same HttpResponse and returns it, however the cookies have invalid values.
The attached testcase triggers the problem in the unit tests.
Change History (14)
comment:1 Changed 5 years ago by
|Patch needs improvement:||unset|
|Status:||new → assigned|
|Triage Stage:||Unreviewed → Accepted|