From 4bab173237452a1fcebe7f5c6eead6d5c9469324 Mon Sep 17 00:00:00 2001 From: n9k Date: Mon, 7 Mar 2022 07:11:49 +0000 Subject: [PATCH] Add Content Security Policy meta tags --- anonstream/routes/core.py | 7 +++++- anonstream/routes/nojs.py | 6 +++++ anonstream/routes/wrappers.py | 11 ++++++--- anonstream/static/anonstream.js | 26 ++++++++++++-------- anonstream/templates/home.html | 3 ++- anonstream/templates/macros/user.html | 4 +-- anonstream/templates/nojs_chat_form.html | 9 ++++--- anonstream/templates/nojs_chat_messages.html | 17 ++++++++++++- anonstream/templates/nojs_chat_users.html | 19 +++++++++++--- anonstream/templates/nojs_info.html | 3 ++- anonstream/templates/nojs_stream.html | 3 ++- anonstream/utils/security.py | 7 ++++++ 12 files changed, 89 insertions(+), 26 deletions(-) create mode 100644 anonstream/utils/security.py diff --git a/anonstream/routes/core.py b/anonstream/routes/core.py index 08bf202..101bb08 100644 --- a/anonstream/routes/core.py +++ b/anonstream/routes/core.py @@ -5,11 +5,16 @@ from anonstream.segments import segments from anonstream.stream import is_online, get_stream_uptime from anonstream.user import watched from anonstream.routes.wrappers import with_user_from, auth_required +from anonstream.utils.security import generate_csp @current_app.route('/') @with_user_from(request) async def home(user): - return await render_template('home.html', user=user) + return await render_template( + 'home.html', + csp=generate_csp(), + user=user, + ) @current_app.route('/stream.mp4') @with_user_from(request) diff --git a/anonstream/routes/nojs.py b/anonstream/routes/nojs.py index 3391b0a..f41ab85 100644 --- a/anonstream/routes/nojs.py +++ b/anonstream/routes/nojs.py @@ -8,6 +8,7 @@ from anonstream.routes.wrappers import with_user_from, render_template_with_etag from anonstream.helpers.chat import get_scrollback from anonstream.helpers.user import get_default_name from anonstream.utils.chat import generate_nonce +from anonstream.utils.security import generate_csp from anonstream.utils.user import concatenate_for_notice CONFIG = current_app.config @@ -18,6 +19,7 @@ USERS_BY_TOKEN = current_app.users_by_token async def nojs_stream(user): return await render_template( 'nojs_stream.html', + csp=generate_csp(), user=user, ) @@ -28,6 +30,7 @@ async def nojs_info(user): uptime, viewership = get_stream_uptime_and_viewership() return await render_template( 'nojs_info.html', + csp=generate_csp(), user=user, viewership=viewership, uptime=uptime, @@ -40,6 +43,7 @@ async def nojs_info(user): async def nojs_chat_messages(user): return await render_template_with_etag( 'nojs_chat_messages.html', + {'csp': generate_csp()}, user=user, users_by_token=USERS_BY_TOKEN, messages=get_scrollback(current_app.messages), @@ -58,6 +62,7 @@ async def nojs_chat_users(user): users_by_presence = get_users_by_presence() return await render_template_with_etag( 'nojs_chat_users.html', + {'csp': generate_csp()}, user=user, get_default_name=get_default_name, users_watching=users_by_presence[Presence.WATCHING], @@ -73,6 +78,7 @@ async def nojs_chat_form(user): prefer_chat_form = request.args.get('landing') != 'appearance' return await render_template( 'nojs_chat_form.html', + csp=generate_csp(), user=user, state=state, prefer_chat_form=prefer_chat_form, diff --git a/anonstream/routes/wrappers.py b/anonstream/routes/wrappers.py index ca1ae14..e93e888 100644 --- a/anonstream/routes/wrappers.py +++ b/anonstream/routes/wrappers.py @@ -86,11 +86,16 @@ def with_user_from(context): return with_user_from_context -async def render_template_with_etag(*args, **kwargs): - rendered_template = await render_template(*args, **kwargs) - tag = hashlib.sha256(rendered_template.encode()).hexdigest() +async def render_template_with_etag(template, deferred_kwargs, **kwargs): + render = await render_template(template, **kwargs) + tag = hashlib.sha256(render.encode()).hexdigest() etag = f'W/"{tag}"' if request.if_none_match.contains_weak(tag): return '', 304, {'ETag': etag} else: + rendered_template = await render_template( + template, + **deferred_kwargs, + **kwargs, + ) return rendered_template, {'ETag': etag} diff --git a/anonstream/static/anonstream.js b/anonstream/static/anonstream.js index bd1e1fd..3eefa3a 100644 --- a/anonstream/static/anonstream.js +++ b/anonstream/static/anonstream.js @@ -2,10 +2,10 @@ const TOKEN = document.body.dataset.token; const TOKEN_HASH = document.body.dataset.tokenHash; +/* Content Security Policy nonce */ +const CSP = document.body.dataset.csp; + /* insert js-only markup */ -const jsmarkup_style_color = '' -const jsmarkup_style_tripcode_display = '' -const jsmarkup_style_tripcode_colors = '' const jsmarkup_stream = `` const jsmarkup_info = '
'; const jsmarkup_info_float = ''; @@ -57,18 +57,24 @@ const jsmarkup_chat_form = `\ `; -const insert_jsmarkup = () => {jsmarkup_info_float_viewership +const insert_jsmarkup = () => { if (document.getElementById("style-color") === null) { - const parent = document.head; - parent.insertAdjacentHTML("beforeend", jsmarkup_style_color); + const style_color = document.createElement("style"); + style_color.id = "style-color"; + style_color.nonce = CSP; + document.head.insertAdjacentElement("beforeend", style_color); } if (document.getElementById("style-tripcode-display") === null) { - const parent = document.head; - parent.insertAdjacentHTML("beforeend", jsmarkup_style_tripcode_display); + const style_tripcode_display = document.createElement("style"); + style_tripcode_display.id = "style-tripcode-display"; + style_tripcode_display.nonce = CSP; + document.head.insertAdjacentElement("beforeend", style_tripcode_display); } if (document.getElementById("style-tripcode-colors") === null) { - const parent = document.head; - parent.insertAdjacentHTML("beforeend", jsmarkup_style_tripcode_colors); + const style_tripcode_colors = document.createElement("style"); + style_tripcode_colors.id = "style-tripcode-colors"; + style_tripcode_colors.nonce = CSP; + document.head.insertAdjacentElement("beforeend", style_tripcode_colors); } if (document.getElementById("stream_js") === null) { const parent = document.getElementById("stream"); diff --git a/anonstream/templates/home.html b/anonstream/templates/home.html index 5973d13..9c21136 100644 --- a/anonstream/templates/home.html +++ b/anonstream/templates/home.html @@ -3,9 +3,10 @@ + - +
diff --git a/anonstream/templates/macros/user.html b/anonstream/templates/macros/user.html index 8aa85b8..281f63d 100644 --- a/anonstream/templates/macros/user.html +++ b/anonstream/templates/macros/user.html @@ -13,7 +13,7 @@ ## {{- ' ' | safe -}} {%- endif -%} - + {{- user.name or get_default_name(user) -}} {%- if not user.broadcaster and user.name is none -%} {{ user.tag }} @@ -22,6 +22,6 @@ {%- if user.tripcode -%}   {{- '' -}} - {{ user.tripcode.digest }} + {{ user.tripcode.digest }} {%- endif -%} {% endmacro %} diff --git a/anonstream/templates/nojs_chat_form.html b/anonstream/templates/nojs_chat_form.html index 52ebecb..998f30b 100644 --- a/anonstream/templates/nojs_chat_form.html +++ b/anonstream/templates/nojs_chat_form.html @@ -3,7 +3,8 @@ - diff --git a/anonstream/templates/nojs_chat_users.html b/anonstream/templates/nojs_chat_users.html index dda922f..8f0b869 100644 --- a/anonstream/templates/nojs_chat_users.html +++ b/anonstream/templates/nojs_chat_users.html @@ -4,8 +4,9 @@ + - @@ -93,7 +106,7 @@
Watching ({{ users_watching | length }})
    {% for user_listed in users_watching %} -
  • +
  • {{- appearance(user_listed, insignia_class='user__insignia', name_class='user__name', tag_class='user__name__tag') -}} {%- if user.token == user_listed.token %} (You){% endif -%}
  • @@ -103,7 +116,7 @@
    Not watching ({{ users_notwatching | length }})
      {% for user_listed in users_notwatching %} -
    • +
    • {{- appearance(user_listed, insignia_class='user__insignia', name_class='user__name', tag_class='user__name__tag') -}} {%- if user.token == user_listed.token %} (You){% endif -%}
    • diff --git a/anonstream/templates/nojs_info.html b/anonstream/templates/nojs_info.html index 3896ea8..0955cdf 100644 --- a/anonstream/templates/nojs_info.html +++ b/anonstream/templates/nojs_info.html @@ -3,8 +3,9 @@ + -