From 1236c4d7f040fed1c2a60063715ab76d9ab2de2d Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Jul 20 2016 21:20:45 +0000 Subject: [PATCH 1/5] Add a clean_input module in hubs.widget This allows to clean the input provided by the users to ensure there is nothing malicious in it. --- diff --git a/hubs/widgets/clean_input.py b/hubs/widgets/clean_input.py new file mode 100644 index 0000000..46bccbc --- /dev/null +++ b/hubs/widgets/clean_input.py @@ -0,0 +1,40 @@ +import urlparse + +import bleach + + +def filter_img_src(name, value): + ''' Filter in img html tags images coming from a different domain. ''' + import hubs.app + if name in ('alt', 'height', 'width', 'class'): + return True + if name == 'src': + p = urlparse.urlparse(value) + return (not p.netloc) or p.netloc == urlparse.urlparse( + hubs.app.app.config['APP_URL']).netloc + return False + + +def clean(text, ignore=None): + """ For a given html text, escape everything we do not want to support + to avoid potential security breach. + """ + if ignore and not isinstance(ignore, (tuple, set, list)): + ignore = [ignore] + + attrs = bleach.ALLOWED_ATTRIBUTES + if not ignore or not 'img' in ignore: + attrs['img'] = filter_img_src + + tags = bleach.ALLOWED_TAGS + [ + 'p', 'br', 'div', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', + 'table', 'td', 'tr', 'th', + 'col', 'tbody', 'pre', 'img', 'hr', 'dl', 'dt', 'dd', 'span', + 'kbd', 'var', + ] + if ignore: + for tag in ignore: + if tag in tags: + tags.remove(tag) + + return bleach.clean(text, tags=tags, attributes=attrs) diff --git a/requirements.txt b/requirements.txt index 01e9cc9..c2dadcf 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,5 @@ arrow +bleach datanommer.models dogpile.cache fedmsg From 6ca3800b1048e98c15f0b753d58265616b7df59a Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Jul 20 2016 21:20:45 +0000 Subject: [PATCH 2/5] Add a library widget where someone can provide a list of links of interest --- diff --git a/hubs/widgets/__init__.py b/hubs/widgets/__init__.py index 2e72e00..a365c3d 100755 --- a/hubs/widgets/__init__.py +++ b/hubs/widgets/__init__.py @@ -4,6 +4,7 @@ from hubs.widgets import rules from hubs.widgets import sticky from hubs.widgets import about from hubs.widgets import badges +from hubs.widgets import library from hubs.widgets import linechart from hubs.widgets import fedmsgstats from hubs.widgets import feed @@ -27,6 +28,7 @@ registry = { 'sticky': sticky, 'about': about, 'badges': badges, + 'library': library, 'linechart': linechart, 'fedmsgstats': fedmsgstats, 'feed': feed, diff --git a/hubs/widgets/library.py b/hubs/widgets/library.py new file mode 100644 index 0000000..8f0dc4b --- /dev/null +++ b/hubs/widgets/library.py @@ -0,0 +1,32 @@ +from hubs.hinting import hint, prefixed as _ +from hubs.widgets.chrome import panel +from hubs.widgets.base import argument +from hubs.widgets import clean_input +from hubs.widgets import templating + +import hubs.validators as validators + +chrome = panel("Library") +template = templating.environment.get_template('templates/library.html') +position = 'both' + + +@argument(name="urls", default=None, + validator=validators.text, + help="A comma separated list of URLs to add to the library.") +def data(session, widget, urls): + urls = [ + clean_input.clean('{0}'.format(u.strip())) + for u in widget.config.get('urls', '').split(',') + if u.strip() + ] + return dict(urls=urls) + + +@hint(topics=[_('hubs.widget.update')]) +def should_invalidate(message, session, widget): + if not message['topic'].endswith('hubs.widget.update'): + return False + if message['msg']['widget']['id'] != widget.id: + return False + return True diff --git a/hubs/widgets/templates/library.html b/hubs/widgets/templates/library.html new file mode 100644 index 0000000..4cbff48 --- /dev/null +++ b/hubs/widgets/templates/library.html @@ -0,0 +1,11 @@ +
+
+
    + {% for url in urls %} +
  • + {{ url }} +
  • + {% endfor %} +
+
+
From a0a5d1403f27e619137e61a251399b4e620a69e7 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Jul 20 2016 21:25:44 +0000 Subject: [PATCH 3/5] Improve the help message on the library widget --- diff --git a/hubs/widgets/library.py b/hubs/widgets/library.py index 8f0dc4b..2169f2f 100644 --- a/hubs/widgets/library.py +++ b/hubs/widgets/library.py @@ -13,7 +13,8 @@ position = 'both' @argument(name="urls", default=None, validator=validators.text, - help="A comma separated list of URLs to add to the library.") + help="A comma separated list of URLs to add to the library. " + "External links must include the whole link (starting with http...") def data(session, widget, urls): urls = [ clean_input.clean('{0}'.format(u.strip())) From 99d00a7fc66be88db371691517494098199d4426 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Jul 20 2016 21:25:57 +0000 Subject: [PATCH 4/5] Ensure the URLs are bytes not unicode before being .strip() --- diff --git a/hubs/widgets/library.py b/hubs/widgets/library.py index 2169f2f..5dd4f5a 100644 --- a/hubs/widgets/library.py +++ b/hubs/widgets/library.py @@ -17,9 +17,9 @@ position = 'both' "External links must include the whole link (starting with http...") def data(session, widget, urls): urls = [ - clean_input.clean('{0}'.format(u.strip())) + clean_input.clean('{0}'.format(u.encode('utf-8').strip())) for u in widget.config.get('urls', '').split(',') - if u.strip() + if u.encode('utf-8').strip() ] return dict(urls=urls) From a6ae66c22f4eee668d4abac590b037c4ea42e762 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Jul 20 2016 21:26:37 +0000 Subject: [PATCH 5/5] Typo in the doc --- diff --git a/hubs/widgets/library.py b/hubs/widgets/library.py index 5dd4f5a..c476ced 100644 --- a/hubs/widgets/library.py +++ b/hubs/widgets/library.py @@ -14,7 +14,7 @@ position = 'both' @argument(name="urls", default=None, validator=validators.text, help="A comma separated list of URLs to add to the library. " - "External links must include the whole link (starting with http...") + "External links must include the whole link (starting with http...)") def data(session, widget, urls): urls = [ clean_input.clean('{0}'.format(u.encode('utf-8').strip()))