from xml.sax.saxutils import quoteattr class SafeHTMLMixin(object): def sanitize(self, s): """sanitize value following https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet#RULE_.231_-_HTML_Escape_Before_Inserting_Untrusted_Data_into_HTML_Element_Content """ if isinstance(s, (list, tuple)): return tuple(self.sanitize(x) for x in s) elif not isinstance(s, SafeHTMLMixin): return quoteattr( s, entities={'"': '"', '/': '/', "'": '''})[1:-1] else: return s def __add__(self, s): return self.__class__(super(SafeHTMLMixin, self).__add__(self.sanitize(s))) def __radd__(self, s): return self.__class__(self.sanitize(s)) + self def __mul__(self, i): return self.__class__(super(SafeHTMLMixin, self).__mul__(i)) def __rmul__(self, i): return self.__class__(super(SafeHTMLMixin, self).__rmul__(i)) def __mod__(self, s): return self.__class__(super(SafeHTMLMixin, self).__mod__(self.sanitize(s))) def __repr__(self): return '%s(%s)' % (self.__class__.__name__, super(SafeHTMLMixin, self).__repr__()) class SafeHTMLStr(SafeHTMLMixin, str): """a string that will sanitize all str concatenated to it (or inserted via format) SafeHTMLStr itself is not quoted:: >>> SafeHTMLStr('') + SafeHTMLStr('