From e9f5e3e91b42cf16fc851bb76aa36757edcbc9c4 Mon Sep 17 00:00:00 2001 From: Blackwell Code <161588956+Blackwellcode@users.noreply.github.com> Date: Thu, 12 Nov 2026 08:51:18 +0100 Subject: [PATCH 01/30] feat(webui): enforce CSP with per-request script nonces script-src drops 'unsafe-inline': inline ", mobile_app_head_tags(), flags=re.S): + digest = hashlib.sha256(body.encode("utf-8")).digest() + _CSP_INJECTED_SCRIPT_HASHES.append("'sha256-" + base64.b64encode(digest).decode("ascii") + "'") + return _CSP_INJECTED_SCRIPT_HASHES + + +# Third-party hosts the UI talks to (chat emotes: BTTV/FFZ/7TV, sub emotes: ivr.fi; +# clip editor slider: cdnjs). Keep in sync with static/chat_emotes.js. +CSP_SCRIPT_HOSTS = "https://cdn.jsdelivr.net https://cdnjs.cloudflare.com" +CSP_STYLE_HOSTS = "https://fonts.googleapis.com https://cdnjs.cloudflare.com" +CSP_IMG_HOSTS = ( + "https://static-cdn.jtvnw.net https://badges.twitch.tv https://cdn.discordapp.com " + "https://cdn.betterttv.net https://cdn.frankerfacez.com https://cdn.7tv.app" +) +CSP_CONNECT_HOSTS = ( + "https://*.googleapis.com https://clients3.google.com " + "https://api.betterttv.net https://api.frankerfacez.com https://7tv.io https://api.ivr.fi" +) + + @app.after_request def set_security_headers(response): response = inject_mobile_app_head(response) @@ -10633,24 +10678,29 @@ def set_security_headers(response): response.headers["X-XSS-Protection"] = "1; mode=block" response.headers["Referrer-Policy"] = "strict-origin-when-cross-origin" # HSTS is set once by nginx (avoid duplicate Strict-Transport-Security headers). - # Default is Report-Only. Set VOD_CSP_ENFORCE=true after overlay/player QA. + # Enforced by default; VOD_CSP_ENFORCE=false falls back to Report-Only. + # Inline - {% endif %} @@ -64,29 +70,29 @@