Timur Izhbulatov — Independent Electronic Music

Avoiding leakage of passwords to log files

Sat, 04 Jun 2011 06:59:00 in Tech stuff | permalink

python

MaskedString still holds the actuall string data which is accessible via __getitem__ but overrides __str__ and __repr__ so that the string is presented in blinded form. This is useful for preventing leakage of sensitive data (card numbers, passwords etc.) to log files.

class MaskedString(str):
    '''
    >>> ms =  MaskedString('foobar')
    >>> ms
    '******'
    >>> str(ms)
    '******'
    >>> ms[:]
    'foobar'
    >>> ms =  MaskedString('foobar', show_last=4)
    >>> str(ms)
    '**obar'
    >>> ms == 'foobar'
    True
    '''
    def __new__(cls, arg, symbol='*', show_last=None):
        return super(MaskedString, cls).__new__(cls, arg)

    def __init__(self, arg, symbol='*', show_last=None):
        super(MaskedString, self).__init__()
        self.symbol = symbol
        self.show_last = show_last or 0

    def __str__(self):
        l = len(self) - self.show_last
        last = ''
        if self.show_last > 0:
            last = self[-self.show_last:]
        return self.symbol * l + last

    def __repr__(self):
        return repr(self.__str__())
import logging
logging.basicConfig(level=logging.INFO)
request = dict(
    user='timur',
    password=MaskedString('secret'),
    card_number=MaskedString('0000000000000000000', show_last=4),
)
logging.info('request: %r', request) 
Output:
INFO:root:request: {'password': '******', 'card_number': '***************0000', 'user': 'timur'}