def assert_failure(self, res, code=None): # counterintuitively, failure to login will return a 200 # (compared to a redirect). self.assertEqual(res.status, 200) # recaptcha is done entirely in JS if code != "BAD_CAPTCHA": self.assertTrue(error_list[code] in _force_unicode(res.body))
def add(cls, link, text): name = c.user.name if c.user_is_loggedin else "<AUTOMATED>" now = datetime.now(g.tz).strftime("%Y-%m-%d %H:%M:%S") text = "[%s: %s] %s" % (name, now, text) rowkey = cls._rowkey(link) column = {uuid1(): _force_unicode(text)} cls._set_values(rowkey, column) return text
def conditional_websafe(text = ''): from wrapped import Templated, CacheStub if text.__class__ == _Unsafe: return text elif isinstance(text, Templated): return _Unsafe(text.render()) elif isinstance(text, CacheStub): return _Unsafe(text) elif text is None: return "" elif text.__class__ != unicode: text = _force_unicode(text) return c_websafe(text)
def alien_blue_html_decode(source, keep_brackets=True): source = _force_unicode(source) # Emulate old Alien Blue's broken HTML decoding # `&amp;` was explicitly rewritten to `&` source = source.replace("&", "&").replace("&", "&") # Angle brackets were replaced with Unicode thingies source = source.replace("<", ".") source = source.replace(">", ".") # So we can figure out if any new brackets were introduced after decoding if not keep_brackets: source = source.replace("<", "").replace(">", "") # Then a general HTML entity replacement pass was made h = HTMLParser.HTMLParser() return h.unescape(source)
def scriptsafe_dumps(obj, **kwargs): """ Like `json.dumps()`, but safe for use in `<script>` blocks. Also nice for response bodies that might be consumed by terrible browsers! You should avoid using this to template data into inline event handlers. When possible, you should do something like this instead: ``` <button onclick="console.log($(this).data('json-thing'))" data-json-thing="${json_thing}"> </button> ``` """ text = _force_unicode(json.dumps(obj, **kwargs)) # wrap the response in _Unsafe so conditional_websafe doesn't touch it # TODO: this might be a hot path soon, C-ify it? return _Unsafe(text.translate(_json_escapes))
def check_for_alien_blue_xss(node, document_html): """Check element for Alien Blue XSS payloads""" def _sniff_bs_node(bs_node): if isinstance(bs_node, BeautifulSoup.NavigableString): return if bs_node.name in {"script", "meta", "base"}: raise SoupAlienBlueXSSError(bs_node) for attr_name, attr_val in bs_node.attrs: # event handlers if attr_name.startswith("on"): raise SoupAlienBlueXSSError(bs_node) attr_val = attr_val.lower() if attr_name == 'href' and attr_val.startswith("javascript"): raise SoupAlienBlueXSSError(bs_node) # lxml doesn't give you any way to get the original source pre-decoding, # try to pull it from the original HTML, abusing the fact that snudown # will put `<table>` and `</table>` on their own lines split_html = document_html.splitlines(True) start_line = node.sourceline - 1 end_line = None if node.getnext() is not None: # get everything before the start of the next tag end_line = node.getnext().sourceline - 1 table_source = _force_unicode(''.join(split_html[start_line:end_line])) table_source = alien_blue_html_decode(table_source) # We can't use `souptest_fragment` here because we don't want to disallow # perfectly reasonable rendered md like `<table><th><td><foo>[...]`. # Just parse the (possibly mangled) markup like a browser would and look # for the low-hanging rotten fruit. Specifically, someone might've escaped # from a title attribute or something similar. bs_root = BeautifulSoup.BeautifulSoup(table_source).contents[0] _sniff_bs_node(bs_root) for bs_child_node in bs_root.nextGenerator(): if bs_child_node is not None: _sniff_bs_node(bs_child_node)
def unsafe(text=''): return _Unsafe(_force_unicode(text))
def websafe_json(text=""): return c_websafe_json(_force_unicode(text))
def jssafe(text=u''): """Prevents text from breaking outside of string literals in JS""" if text.__class__ != unicode: text = _force_unicode(text) # wrap the response in _Unsafe so conditional_websafe doesn't touch it return _Unsafe(text.translate(_js_escapes))
def websafe(text=''): if text.__class__ != unicode: text = _force_unicode(text) #wrap the response in _Unsafe so make_websafe doesn't unescape it return _Unsafe(c_websafe(text))