From 392bc5df6e814c96ab03c6087dd6172d13ad3f89 Mon Sep 17 00:00:00 2001 From: Cyprian Kowalczyk Date: Thu, 9 Apr 2026 21:07:07 -0400 Subject: [PATCH] fix: add Content-Security-Policy and Permissions-Policy headers (#197) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add CSP and Permissions-Policy headers to _security_headers() for defense-in-depth against XSS and unwanted browser feature access. CSP policy: default-src 'self' — only load resources from same origin script-src 'self' — prevent inline/remote script injection style-src 'self' 'unsafe-inline' — allow themes (inline styles) img-src 'self' data: — allow workspace images and data URIs font-src 'self' data: — allow web fonts connect-src 'self' — only allow fetch/XHR to same origin base-uri 'self'; form-action 'self' — prevent base/form injection Permissions-Policy: disable camera, microphone, geolocation. Addresses #193. --- api/helpers.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/api/helpers.py b/api/helpers.py index fe16fb4..e1689df 100644 --- a/api/helpers.py +++ b/api/helpers.py @@ -39,6 +39,16 @@ def _security_headers(handler): handler.send_header('X-Content-Type-Options', 'nosniff') handler.send_header('X-Frame-Options', 'DENY') handler.send_header('Referrer-Policy', 'same-origin') + handler.send_header( + 'Content-Security-Policy', + "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; " + "img-src 'self' data:; font-src 'self' data:; connect-src 'self'; " + "base-uri 'self'; form-action 'self'" + ) + handler.send_header( + 'Permissions-Policy', + 'camera=(), microphone=(), geolocation=()' + ) def j(handler, payload, status: int=200) -> None: