forked from CGM_Public/pretix_original
[SECURITY] Rewrite all links in rich texts
This commit is contained in:
@@ -1,6 +1,12 @@
|
|||||||
|
import urllib.parse
|
||||||
|
|
||||||
import bleach
|
import bleach
|
||||||
import markdown
|
import markdown
|
||||||
|
from bleach import DEFAULT_CALLBACKS
|
||||||
from django import template
|
from django import template
|
||||||
|
from django.core import signing
|
||||||
|
from django.urls import reverse
|
||||||
|
from django.utils.http import is_safe_url
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
|
|
||||||
register = template.Library()
|
register = template.Library()
|
||||||
@@ -48,6 +54,15 @@ ALLOWED_ATTRIBUTES = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def safelink_callback(attrs, new=False):
|
||||||
|
url = attrs.get((None, 'href'), '/')
|
||||||
|
if not is_safe_url(url):
|
||||||
|
signer = signing.Signer(salt='safe-redirect')
|
||||||
|
attrs[None, 'href'] = reverse('redirect') + '?url=' + urllib.parse.quote(signer.sign(url))
|
||||||
|
attrs[None, 'target'] = '_blank'
|
||||||
|
return attrs
|
||||||
|
|
||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
def rich_text(text: str, **kwargs):
|
def rich_text(text: str, **kwargs):
|
||||||
"""
|
"""
|
||||||
@@ -58,5 +73,5 @@ def rich_text(text: str, **kwargs):
|
|||||||
markdown.markdown(text),
|
markdown.markdown(text),
|
||||||
tags=ALLOWED_TAGS,
|
tags=ALLOWED_TAGS,
|
||||||
attributes=ALLOWED_ATTRIBUTES,
|
attributes=ALLOWED_ATTRIBUTES,
|
||||||
))
|
), callbacks=DEFAULT_CALLBACKS + [safelink_callback])
|
||||||
return mark_safe(body_md)
|
return mark_safe(body_md)
|
||||||
|
|||||||
@@ -68,6 +68,18 @@ class EventMiddlewareTest(EventTestMixin, SoupTest):
|
|||||||
|
|
||||||
|
|
||||||
class ItemDisplayTest(EventTestMixin, SoupTest):
|
class ItemDisplayTest(EventTestMixin, SoupTest):
|
||||||
|
def test_link_rewrite(self):
|
||||||
|
q = Quota.objects.create(event=self.event, name='Quota', size=2)
|
||||||
|
item = Item.objects.create(event=self.event, name='Early-bird ticket', default_price=0, active=True,
|
||||||
|
description="http://example.org [Sample](http://example.net)")
|
||||||
|
q.items.add(item)
|
||||||
|
html = self.client.get('/%s/%s/' % (self.orga.slug, self.event.slug)).rendered_content
|
||||||
|
|
||||||
|
self.assertNotIn('href="http://example.org', html)
|
||||||
|
self.assertNotIn('href="http://example.net', html)
|
||||||
|
self.assertIn('href="/redirect/?url=http%3A//example.org%3A', html)
|
||||||
|
self.assertIn('href="/redirect/?url=http%3A//example.net%3A', html)
|
||||||
|
|
||||||
def test_not_active(self):
|
def test_not_active(self):
|
||||||
q = Quota.objects.create(event=self.event, name='Quota', size=2)
|
q = Quota.objects.create(event=self.event, name='Quota', size=2)
|
||||||
item = Item.objects.create(event=self.event, name='Early-bird ticket', default_price=0, active=False)
|
item = Item.objects.create(event=self.event, name='Early-bird ticket', default_price=0, active=False)
|
||||||
|
|||||||
Reference in New Issue
Block a user