46 lines
1.7 KiB
Django/Jinja

{# Initialize an array to collect each CSP directive line #}
{%- set csp_parts = [] %}
{# List of all directives to process dynamically (except img-src) #}
{%- set directives = [
'default-src',
'connect-src',
'frame-ancestors',
'frame-src',
'script-src',
'style-src',
'font-src'
] %}
{# Loop over each directive and build its value from 'self', any unsafe flags, whitelist URLs, and optional Matomo #}
{%- for directive in directives %}
{# Start with the 'self' source #}
{%- set tokens = ["'self'"] %}
{# Add any unsafe flags (unsafe-eval, unsafe-inline) from csp.flags.<directive> #}
{%- for flag in applications | get_csp_flags(application_id, directive) %}
{%- set tokens = tokens + [flag] %}
{%- endfor %}
{# If Matomo feature is enabled, whitelist its script and connect sources #}
{%- if applications | is_feature_enabled('matomo', application_id) and directive in ['script-src','connect-src'] %}
{%- set tokens = tokens + ['{{ web_protocol }}://{{ domains.matomo }}'] %}
{%- endif %}
{# Add any extra hosts/URLs from csp.whitelist.<directive> #}
{%- for url in applications | get_csp_whitelist(application_id, directive) %}
{%- set tokens = tokens + [url] %}
{%- endfor %}
{# Combine into a single directive line and append to csp_parts #}
{%- set csp_parts = csp_parts + [directive ~ ' ' ~ (tokens | join(' ')) ~ ';'] %}
{%- endfor %}
{# Preserve original img-src directive logic (do not loop) #}
{%- set img_src = 'img-src * data: blob:' %}
{%- set csp_parts = csp_parts + [img_src ~ ';'] %}
{# Emit the assembled Content-Security-Policy header and hide any upstream CSP header #}
add_header Content-Security-Policy "{{ csp_parts | join(' ') }}" always;
proxy_hide_header Content-Security-Policy;