Perhaps something along the lines of how Django marks strings as safe /
need escaping for the template engine can be applied here. A
forms.PasswordField might mark its data as "sensitive", and that info
would flow up until the point it is being rendered by the debug templates,
printed to a log file, etc.
Yishai
> Recently I've been a bit embarrassed to receive a 500-error email
> report containing a client of mine's password displayed in clear
> because the admin login view had encountered an unhandled exception.
> This is probably OK in a debug environment but in production this can
> potentially have damaging consequences when handling passwords, credit
> card numbers, etc. It may also go against certain policies and
> standards such as the PCI-DSS (http://en.wikipedia.org/wiki/
> Payment_Card_Industry_Data_Security_Standard).
>
> There is already an open ticket to address this issue:
> https://code.djangoproject.com/ticket/14614
>
> I first wrote a patch allowing a lot of granularity to control which
> POST/GET parameters should get obfuscated when producing the error
> logs: https://code.djangoproject.com/attachment/ticket/14614/14614.obfuscate-request-parameters.diff
>
> Russell pointed out that this implementation approach was overly
> complicated. It also doesn't address the stack frame variables being
> logged in some situations. So I've posted another patch with a more
> radical approach, where all stack frame variables and the request's
> information are systematically and entirely omitted from the logs for
> exceptions occurring in views marked with the @sensitive decorator:
> https://code.djangoproject.com/attachment/ticket/14614/14614.sensitive-request.diff
I think we probably do need to provide something here. I'm concerned
that a 'sensitive' decorator puts the decision in the hands of the app
writer, which may well not be appropriate. For example, in one case I'm
involved in, half of the data entered in the admin in sensitive to some
degree, but my ability to debug errors could be seriously hindered if
the whole thing had 'sensitive' slapped on it. (Thankfully, the data
isn't too critical, and it is enough that I just delete the error
e-mails once I've dealt with them).
So, the 'sensitive' decorator might be appropriate for login, and
possible some other views, but I'm concerned it is still going to leave
other important situations with no practical solution.
Would it possible to make the sensitive decorator add some kind of
strategy object to the request, which itself is responsible for the
filtering, rather than a simple boolean flag? The strategy object
interface might be:
class ExceptionReporterFilter(object):
def show_request(self, request):
# return True or False
def filter_request_POST(self, request, post_dict):
# if show_request is True, this is passed request.POST
# and returns a sanitised version
def show_traceback(self, request):
# True or false
def show_traceback_vars(self, request):
# called only if show_traceback() returns True
def filter_traceback_vars(self, request, tb_frame, vars):
# filters vars to be shown at each level.
OK, could get carried away there - maybe we should start simple, e.g.
just 'show_request' and 'show_traceback_vars'. But something like that
would allow us to provide a working 'sensitive' decorator, but with a
mechanism that allows for something more fine-grained, and allows us to
add more features to it easily in the future. For the admin and CBVs it
would work as well, since there are always places you can override a
method and attach something to the request object.
If I'm thinking correctly, with an additional method like
'filter_settings', it might be possible to have a default
ExceptionReporterFilter that does the filtering of settings that is
currently hardcoded into django/views/debug.py.
Regards,
Luke
--
"The truth will set your teeth free." (Calvin and Hobbes)
Luke Plant || http://lukeplant.me.uk/
I'm not quite sure what you're saying. In my proposal above, the
'filter_traceback_vars' would only be used if 'show_traceback_vars'
returned True, and by default it would return all vars. So you wouldn't
be forced to do any filtering on that level.
Since you could re-use your filtering class for multiple views, and you
can implement it how you want, there would be no need to repeat the
definition of the filtering.
> I wonder if it would make sense to handle the traceback and vars
> filtering with a mechanism similar to __traceback_hide__. This would
> allow controlling leakage per frame and make it less likely to be
> missed on view.
>
> Example:
> def do_stuff():
> ...
> do_stuff.__traceback_filter_vars__ = ['credit_card', 'password',
> 'launch_codes']
I'm not sure this even possible - can you go from a traceback frame to
the *function* object? __traceback_hide__ is a local attribute, not a
function attribute.
We could do the same with __traceback_filter_vars__ and make a local
variable. But that could be an implementation detail of the
ExceptionReporterFilter (just as respecting __traceback_hide__ would be).
Luke
--
"Trouble: Luck can't last a lifetime, unless you die young."
(despair.com)
Luke Plant || http://lukeplant.me.uk/