From e2d9d66a22f9004c0349f6aa9f8762fa558bdee8 Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Thu, 9 Jan 2020 11:37:19 +0100 Subject: [PATCH] Fixed #23004 -- Added request.META filtering to SafeExceptionReporterFilter. Co-authored-by: Ryan Castner --- django/views/debug.py | 9 +++++++++ django/views/templates/technical_500.html | 2 +- django/views/templates/technical_500.txt | 2 +- docs/howto/error-reporting.txt | 10 ++++++---- docs/releases/3.1.txt | 6 +++++- tests/view_tests/tests/test_debug.py | 18 ++++++++++++++++++ 6 files changed, 40 insertions(+), 7 deletions(-) diff --git a/django/views/debug.py b/django/views/debug.py index 608282c232..ae2b68ab70 100644 --- a/django/views/debug.py +++ b/django/views/debug.py @@ -123,6 +123,14 @@ class SafeExceptionReporterFilter(ExceptionReporterFilter): settings_dict[k] = self.cleanse_setting(k, getattr(settings, k)) return settings_dict + def get_safe_request_meta(self, request): + """ + Return a dictionary of request.META with sensitive values redacted. + """ + if not hasattr(request, 'META'): + return {} + return {k: self.cleanse_setting(k, v) for k, v in request.META.items()} + def is_active(self, request): """ This filter is to add safety in production environments (i.e. DEBUG @@ -296,6 +304,7 @@ class ExceptionReporter: 'unicode_hint': unicode_hint, 'frames': frames, 'request': self.request, + 'request_meta': self.filter.get_safe_request_meta(self.request), 'user_str': user_str, 'filtered_POST_items': list(self.filter.get_post_parameters(self.request).items()), 'settings': self.filter.get_safe_settings(), diff --git a/django/views/templates/technical_500.html b/django/views/templates/technical_500.html index b01b00c8e6..a63c7183e6 100644 --- a/django/views/templates/technical_500.html +++ b/django/views/templates/technical_500.html @@ -438,7 +438,7 @@ Exception Value: {{ exception_value|force_escape }} - {% for var in request.META.items|dictsort:0 %} + {% for var in request_meta.items|dictsort:0 %} {{ var.0 }}
{{ var.1|pprint }}
diff --git a/django/views/templates/technical_500.txt b/django/views/templates/technical_500.txt index c9f70af797..f06a1a499e 100644 --- a/django/views/templates/technical_500.txt +++ b/django/views/templates/technical_500.txt @@ -50,7 +50,7 @@ FILES:{% for k, v in request_FILES_items %} COOKIES:{% for k, v in request_COOKIES_items %} {{ k }} = {{ v|stringformat:"r" }}{% empty %} No cookie data{% endfor %} -META:{% for k, v in request.META.items|dictsort:0 %} +META:{% for k, v in request_meta.items|dictsort:0 %} {{ k }} = {{ v|stringformat:"r" }}{% endfor %} {% else %}Request data not supplied {% endif %} diff --git a/docs/howto/error-reporting.txt b/docs/howto/error-reporting.txt index a4cb5d2a1a..e145897b2a 100644 --- a/docs/howto/error-reporting.txt +++ b/docs/howto/error-reporting.txt @@ -277,8 +277,9 @@ following attributes and methods: .. versionadded:: 3.1 - A compiled regular expression object used to match settings considered - as sensitive. By default equivalent to:: + A compiled regular expression object used to match settings and + ``request.META`` values considered as sensitive. By default equivalent + to:: import re @@ -289,8 +290,9 @@ following attributes and methods: Returns ``True`` to activate the filtering in :meth:`get_post_parameters` and :meth:`get_traceback_frame_variables`. By default the filter is active if :setting:`DEBUG` is ``False``. Note - that sensitive settings are always filtered, as described in the - :setting:`DEBUG` documentation. + that sensitive ``request.META`` values are always filtered along with + sensitive setting values, as described in the :setting:`DEBUG` + documentation. .. method:: get_post_parameters(request) diff --git a/docs/releases/3.1.txt b/docs/releases/3.1.txt index 48df0a0d66..29e5e22314 100644 --- a/docs/releases/3.1.txt +++ b/docs/releases/3.1.txt @@ -161,9 +161,13 @@ Email Error Reporting ~~~~~~~~~~~~~~~ +* :class:`django.views.debug.SafeExceptionReporterFilter` now filters sensitive + values from ``request.META`` in exception reports. + * The new :attr:`.SafeExceptionReporterFilter.cleansed_substitute` and :attr:`.SafeExceptionReporterFilter.hidden_settings` attributes allow - customization of sensitive settings filtering in exception reports. + customization of sensitive settings and ``request.META`` filtering in + exception reports. * The technical 404 debug view now respects :setting:`DEFAULT_EXCEPTION_REPORTER_FILTER` when applying settings diff --git a/tests/view_tests/tests/test_debug.py b/tests/view_tests/tests/test_debug.py index 9becfc77d0..020af1a19c 100644 --- a/tests/view_tests/tests/test_debug.py +++ b/tests/view_tests/tests/test_debug.py @@ -1224,6 +1224,24 @@ class ExceptionReporterFilterTests(ExceptionReportTestMixin, LoggingCaptureMixin {'login': 'cooper', 'password': reporter_filter.cleansed_substitute}, ) + def test_request_meta_filtering(self): + request = self.rf.get('/', HTTP_SECRET_HEADER='super_secret') + reporter_filter = SafeExceptionReporterFilter() + self.assertEqual( + reporter_filter.get_safe_request_meta(request)['HTTP_SECRET_HEADER'], + reporter_filter.cleansed_substitute, + ) + + def test_exception_report_uses_meta_filtering(self): + response = self.client.get('/raises500/', HTTP_SECRET_HEADER='super_secret') + self.assertNotIn(b'super_secret', response.content) + response = self.client.get( + '/raises500/', + HTTP_SECRET_HEADER='super_secret', + HTTP_X_REQUESTED_WITH='XMLHttpRequest', + ) + self.assertNotIn(b'super_secret', response.content) + class CustomExceptionReporterFilter(SafeExceptionReporterFilter): cleansed_substitute = 'XXXXXXXXXXXXXXXXXXXX'