Fixed #33606 -- Cleansed sessionid cookie in error reports.

Co-authored-by: Simon Charette <charette.s@gmail.com>
This commit is contained in:
Tobias Bengfort 2022-10-26 12:30:44 +02:00 committed by Carlton Gibson
parent b440493eaa
commit 350455b666
4 changed files with 31 additions and 7 deletions

View File

@ -110,7 +110,7 @@ class SafeExceptionReporterFilter:
cleansed_substitute = "********************"
hidden_settings = _lazy_re_compile(
"API|TOKEN|KEY|SECRET|PASS|SIGNATURE", flags=re.I
"API|TOKEN|KEY|SECRET|PASS|SIGNATURE|HTTP_COOKIE", flags=re.I
)
def cleanse_setting(self, key, value):
@ -118,10 +118,13 @@ class SafeExceptionReporterFilter:
Cleanse an individual setting key/value of sensitive content. If the
value is a dictionary, recursively cleanse the keys in that dictionary.
"""
try:
is_sensitive = self.hidden_settings.search(key)
except TypeError:
is_sensitive = False
if key == settings.SESSION_COOKIE_NAME:
is_sensitive = True
else:
try:
is_sensitive = self.hidden_settings.search(key)
except TypeError:
is_sensitive = False
if is_sensitive:
cleansed = self.cleansed_substitute
@ -158,6 +161,14 @@ class SafeExceptionReporterFilter:
return {}
return {k: self.cleanse_setting(k, v) for k, v in request.META.items()}
def get_safe_cookies(self, request):
"""
Return a dictionary of request.COOKIES with sensitive values redacted.
"""
if not hasattr(request, "COOKIES"):
return {}
return {k: self.cleanse_setting(k, v) for k, v in request.COOKIES.items()}
def is_active(self, request):
"""
This filter is to add safety in production environments (i.e. DEBUG
@ -359,6 +370,7 @@ class ExceptionReporter:
"frames": frames,
"request": self.request,
"request_meta": self.filter.get_safe_request_meta(self.request),
"request_COOKIES_items": self.filter.get_safe_cookies(self.request).items(),
"user_str": user_str,
"filtered_POST_items": list(
self.filter.get_post_parameters(self.request).items()
@ -376,7 +388,6 @@ class ExceptionReporter:
if self.request is not None:
c["request_GET_items"] = self.request.GET.items()
c["request_FILES_items"] = self.request.FILES.items()
c["request_COOKIES_items"] = self.request.COOKIES.items()
c["request_insecure_uri"] = self._get_raw_insecure_uri()
c["raising_view_name"] = get_caller(self.request)

View File

@ -281,7 +281,11 @@ following attributes and methods:
import re
re.compile(r'API|TOKEN|KEY|SECRET|PASS|SIGNATURE', flags=re.IGNORECASE)
re.compile(r'API|TOKEN|KEY|SECRET|PASS|SIGNATURE|HTTP_COOKIE', flags=re.IGNORECASE)
.. versionchanged:: 4.2
``HTTP_COOKIE`` was added.
.. method:: is_active(request)

View File

@ -176,6 +176,9 @@ Forms
* :func:`~django.forms.models.modelform_factory` now respects the
``formfield_callback`` attribute of the ``form``s ``Meta``.
* Session cookies are now treated as credentials and therefore hidden and
replaced with stars (``**********``) in error reports.
Generic Views
~~~~~~~~~~~~~

View File

@ -1696,6 +1696,12 @@ class ExceptionReporterFilterTests(
)
self.assertNotIn(b"super_secret", response.content)
@override_settings(SESSION_COOKIE_NAME="djangosession")
def test_cleanse_session_cookie_value(self):
self.client.cookies.load({"djangosession": "should not be displayed"})
response = self.client.get("/raises500/")
self.assertNotContains(response, "should not be displayed", status_code=500)
class CustomExceptionReporterFilter(SafeExceptionReporterFilter):
cleansed_substitute = "XXXXXXXXXXXXXXXXXXXX"