diff --git a/pyproject.toml b/pyproject.toml index a7c762f..f4e32de 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,6 +39,7 @@ dependencies = [ "Pillow", "pillow-heif", "IP2Location", + "bleach" ] [tool.setuptools.packages.find] diff --git a/src/snek/app.py b/src/snek/app.py index c13670e..b4ddec9 100644 --- a/src/snek/app.py +++ b/src/snek/app.py @@ -59,6 +59,7 @@ from snek.view.channel import ChannelAttachmentView from snek.view.channel import ChannelView from snek.view.settings.containers import ContainersIndexView, ContainersCreateView, ContainersUpdateView, ContainersDeleteView from snek.webdav import WebdavApplication +from snek.system.template import sanitize_html from snek.sgit import GitApplication SESSION_KEY = b"c79a0c5fda4b424189c427d28c9f7c34" @@ -124,6 +125,7 @@ class Application(BaseApplication): self.jinja2_env.add_extension(LinkifyExtension) self.jinja2_env.add_extension(PythonExtension) self.jinja2_env.add_extension(EmojiExtension) + self.jinja2_env.filters['sanitize'] = sanitize_html self.time_start = datetime.now() self.ssh_host = "0.0.0.0" self.ssh_port = 2242 diff --git a/src/snek/system/template.py b/src/snek/system/template.py index 335c01c..4c023a7 100644 --- a/src/snek/system/template.py +++ b/src/snek/system/template.py @@ -10,6 +10,8 @@ from bs4 import BeautifulSoup from jinja2 import TemplateSyntaxError, nodes from jinja2.ext import Extension from jinja2.nodes import Const +import bleach + emoji.EMOJI_DATA[''] = { "en": ":snek1:", @@ -78,6 +80,36 @@ emoji.EMOJI_DATA[ ] = {"en": ":a1:", "status": 2, "E": 0.6, "alias": [":a1:"]} +ALLOWED_TAGS = list(bleach.sanitizer.ALLOWED_TAGS) + [ + "img", "video", "audio", "source", "iframe", "picture", "span" +] +ALLOWED_ATTRIBUTES = { + **bleach.sanitizer.ALLOWED_ATTRIBUTES, + "img": ["src", "alt", "title", "width", "height"], + "a": ["href", "title", "target", "rel", "referrerpolicy", "class"], + "iframe": ["src", "width", "height", "frameborder", "allow", "allowfullscreen", "title", "referrerpolicy", "style"], + "video": ["src", "controls", "width", "height"], + "audio": ["src", "controls"], + "source": ["src", "type"], + "span": ["class"], + "picture": [], +} + + + + + +def sanitize_html(value): + return bleach.clean( + value, + tags=ALLOWED_TAGS, + attributes=ALLOWED_ATTRIBUTES, + protocols=bleach.sanitizer.ALLOWED_PROTOCOLS + ["data"], + strip=True, + ) + + + def set_link_target_blank(text): soup = BeautifulSoup(text, "html.parser")