Browse Source

Fixed #23004 -- Added request.META filtering to SafeExceptionReporterFilter.

Co-authored-by: Ryan Castner <castner.rr@gmail.com>
Carlton Gibson 5 years ago
parent
commit
e2d9d66a22

+ 9 - 0
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(),

+ 1 - 1
django/views/templates/technical_500.html

@@ -438,7 +438,7 @@ Exception Value: {{ exception_value|force_escape }}
       </tr>
     </thead>
     <tbody>
-      {% for var in request.META.items|dictsort:0 %}
+      {% for var in request_meta.items|dictsort:0 %}
         <tr>
           <td>{{ var.0 }}</td>
           <td class="code"><pre>{{ var.1|pprint }}</pre></td>

+ 1 - 1
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 %}

+ 6 - 4
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)
 

+ 5 - 1
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

+ 18 - 0
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'