Django error reporting emails: env vars leak info
OK, missed this in my previous checking, but apparently the django team had approximately this bug logged & closed it as will-not-fix 6 years ago:
https://code.djangoproject.com/ticket/7472
I will take it up with them, since I believe that django has made substantial security progress in the intervening time and now may want to, and have some simple ways to, address this. :)
In the meantime, if you use this email-the-admins function please be cognizant of the risk. If you send these emails then I would strongly urge you to leave or place all secrets/passwords/keys/certs/etc in python config files, and to ensure you are scrubbing the (unix) environment that is passed to your django web service.
I ran into the same issue, and addressed it by creating custom Middleware, as described in the Django docs. This approach assumes that you know the names of the env variables that you want to hide from error pages / emails, and that you don't actually need these variables present in every request. You can then filter them out from the request.META dictionary before the error response gets generated:
class RequestSafetyMiddleware(object):
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
request.META.pop('TOP_SECRET', None)
response = self.get_response(request)
return response
I hope this helps! I wish Django applied the same safety obfuscation rules to env variables as it applies to settings, so this would not even be an issue.
In the case of using mod_wsgi
with Apache, environment variables (set through the Apache SetEnv
directive or otherwise) are passed to the application
function in the first environ
argument.
In order to be able to access these environment variables in settings.py
(or elsewhere), it is convenient to copy them to os.environ
, using e.g.
os.environ['TOP_SECRET'] = environ['TOP_SECRET']
After this, environ
is passed to django.core.handlers.wsgi.WSGIHandler
(via django.core.wsgi.get_wsgi_application
) where it eventually makes it's way to the error reports.
The TOP_SECRET
key doesn't need to be retained in environ
after it is copied to os.environ
, so changing the line above to os.environ['TOP_SECRET'] = environ.pop('TOP_SECRET', '')
removes it from the error reports.
Putting it all together, my wsgi.py
file is as follows:
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "App.settings")
env_variables_to_pass = ['TOP_SECRET']
def application(environ, start_response):
# pass the WSGI environment variables on through to os.environ
for var in env_variables_to_pass:
os.environ[var] = environ.pop(var, '')
return get_wsgi_application()(environ, start_response)
This means that the required environment variables are available in os.environ
where needed, but they don't show up in the error reports.
It's possible that I've missed something here, but this does seem to be working for me. If there is a reason not to do this, please post a comment. It may be safer to create a copy of the environ
dictionary first, i.e. my_environ = copy.deepcopy(environ)
, then use that instead of environ
directly.
Note also that other sensitive variables (e.g. passwords in POST
requests) should be filtered instead.