summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTobias Bengfort <tobias.bengfort@posteo.de>2022-10-26 12:30:44 +0200
committerCarlton Gibson <carlton@noumenal.es>2022-10-26 14:39:58 +0200
commit350455b666a289d336fca770578887ce51f1aebe (patch)
tree0b9811c660d1d73a2894fd145ac304bc4ba54b49
parentb440493eaad28f093278a7a6981386dd5a989a74 (diff)
Fixed #33606 -- Cleansed sessionid cookie in error reports.
Co-authored-by: Simon Charette <charette.s@gmail.com>
-rw-r--r--django/views/debug.py23
-rw-r--r--docs/howto/error-reporting.txt6
-rw-r--r--docs/releases/4.2.txt3
-rw-r--r--tests/view_tests/tests/test_debug.py6
4 files changed, 31 insertions, 7 deletions
diff --git a/django/views/debug.py b/django/views/debug.py
index ea06224bf6..30a1dbc6da 100644
--- a/django/views/debug.py
+++ b/django/views/debug.py
@@ -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)
diff --git a/docs/howto/error-reporting.txt b/docs/howto/error-reporting.txt
index 6cd69d5857..b808a0a981 100644
--- a/docs/howto/error-reporting.txt
+++ b/docs/howto/error-reporting.txt
@@ -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)
diff --git a/docs/releases/4.2.txt b/docs/releases/4.2.txt
index 9c6526a3a0..58e4bd12ac 100644
--- a/docs/releases/4.2.txt
+++ b/docs/releases/4.2.txt
@@ -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
~~~~~~~~~~~~~
diff --git a/tests/view_tests/tests/test_debug.py b/tests/view_tests/tests/test_debug.py
index 5a07131349..7224a2b6b6 100644
--- a/tests/view_tests/tests/test_debug.py
+++ b/tests/view_tests/tests/test_debug.py
@@ -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"