{# 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, and whitelisted URLs #} {%- for directive in directives %} {# Start with the 'self' source #} {%- set tokens = ["'self'"] %} {# Add any unsafe flags (unsafe-eval, unsafe-inline) from csp.flags. #} {%- for flag in applications | get_csp_flags(application_id, directive) %} {%- set tokens = tokens + [flag] %} {%- endfor %} {# Add any extra hosts/URLs from csp.whitelist. #} {%- 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;