Django Debug - Meta Data Scrubbing

Sept. 15, 2020

Have you ever wondered why some settings appear as '******' on the Django debugger?

Well Django applies an exception reporter filter to request data and settings before they are displayed on the debug view.

Here is a snippet from the default SafeExceptionReporterFilter class.

class SafeExceptionReporterFilter:
    """
    Use annotations made by the sensitive_post_parameters and
    sensitive_variables decorators to filter out sensitive information.
    """
    cleansed_substitute = '********************'
    hidden_settings = _lazy_re_compile('API|TOKEN|KEY|SECRET|PASS|SIGNATURE', flags=re.I)

    def cleanse_setting(self, key, value):
        """
        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 is_sensitive:
            cleansed = self.cleansed_substitute
        elif isinstance(value, dict):
            cleansed = {k: self.cleanse_setting(k, v) for k, v in value.items()}
        elif isinstance(value, list):
            cleansed = [self.cleanse_setting('', v) for v in value]
        elif isinstance(value, tuple):
            cleansed = tuple([self.cleanse_setting('', v) for v in value])
        else:
            cleansed = value

        if callable(cleansed):
            cleansed = CallableSettingWrapper(cleansed)

        return cleansed

The above snippet demonstrates how Django scrubs settings before they are displayed on the debug page. As you can see any settings that match following names are obfuscated:

As with most things in Django this functionality can be switched out with a custom class using the DEFAULTEXCEPTIONREPORTER_FILTER setting.

So suppose for example you make use of Azure for hosting and various other things. Azure makes use of connection strings to connect to certain services so let's assume we want to obfuscate any setting that matches CONNECTIONSTRING. We could subclass SafeExceptionReporterFilter with our own hiddensettings regex pattern and update the DEFAUTEXCEPTIONREPORTER_FILTER setting to make use of our class.

class CustomSafeExceptionReporterFilter(SafeExceptionReporterFilter):
    """
    Custom settings scrubber which obfuscates `CONNECTION_STRING` as well.
    """

    hidden_settings = _lazy_re_compile('API|TOKEN|KEY|SECRET|PASS|SIGNATURE|CONNECTION_STRING', flags=re.I)