diff --git a/kitsune/settings.py b/kitsune/settings.py index 041c9050a02..cdfd92bb031 100644 --- a/kitsune/settings.py +++ b/kitsune/settings.py @@ -1265,14 +1265,12 @@ def setup_logger(name, formatter_str, level=logging.DEBUG): "DIRECTIVES": { "default-src": [NONE], "script-src": [ - SELF, - "https://*.mozilla.org", - "https://*.webservices.mozgcp.net", - "https://*.google-analytics.com", - "https://*.googletagmanager.com", + # Third-party scripts injected at runtime without our nonce, so they + # must stay host-allowlisted (don't add 'strict-dynamic'). + "https://www.googletagmanager.com", + "https://www.google-analytics.com", f"https://{MATOMO_MZLA_CDN_HOST}", "https://pontoon.mozilla.org", - "https://*.jsdelivr.net", NONCE, ], "img-src": [ @@ -1304,7 +1302,6 @@ def setup_logger(name, formatter_str, level=logging.DEBUG): "style-src": [ SELF, "https://*.webservices.mozgcp.net", - "https://*.jsdelivr.net", NONCE, ], "form-action": [ @@ -1330,6 +1327,10 @@ def setup_logger(name, formatter_str, level=logging.DEBUG): if DEBUG: CONTENT_SECURITY_POLICY["DIRECTIVES"]["style-src"].append(UNSAFE_INLINE) CONTENT_SECURITY_POLICY["DIRECTIVES"]["script-src"].extend([UNSAFE_INLINE, UNSAFE_EVAL]) + # GraphiQL (DEBUG-only) loads from jsDelivr; restrict to /npm/ so arbitrary + # /gh/ repo scripts can't be loaded. + CONTENT_SECURITY_POLICY["DIRECTIVES"]["script-src"].append("https://cdn.jsdelivr.net/npm/") + CONTENT_SECURITY_POLICY["DIRECTIVES"]["style-src"].append("https://cdn.jsdelivr.net/npm/") # Trusted Contributor Groups TRUSTED_GROUPS = [ diff --git a/kitsune/sumo/jinja2/base.html b/kitsune/sumo/jinja2/base.html index e6c580139d2..9e3bbb01b75 100644 --- a/kitsune/sumo/jinja2/base.html +++ b/kitsune/sumo/jinja2/base.html @@ -377,9 +377,9 @@ {% if request.LANGUAGE_CODE %} {% if settings.DEV or settings.TEST %} - + {% else %} - + {% endif %} {% endif %} diff --git a/kitsune/urls.py b/kitsune/urls.py index 48210df2ef1..2e40d47595f 100644 --- a/kitsune/urls.py +++ b/kitsune/urls.py @@ -77,8 +77,9 @@ servestatic, kwargs={"document_root": settings.ROOT}, ), - # GraphiQL - path("graphql", csrf_exempt(GraphQLView.as_view(graphiql=True))), + # GraphiQL IDE loads CDN assets, so enable it only for local dev to keep + # that CDN out of the deployed CSP. The GraphQL endpoint stays available. + path("graphql", csrf_exempt(GraphQLView.as_view(graphiql=settings.DEBUG))), re_path( r"^customercare/zendesk/updates/?$", csrf_exempt(ZendeskWebhookView.as_view()),