71 lines
2.9 KiB
Plaintext
71 lines
2.9 KiB
Plaintext
# security-headers.conf — security baseline for the levineuwirth.org vhost.
|
|
#
|
|
# Place at /etc/nginx/snippets/security-headers.conf and `include` it
|
|
# inside the server { } block of the vhost, alongside the other
|
|
# snippets shipped from this repo:
|
|
#
|
|
# server {
|
|
# server_name levineuwirth.org;
|
|
# root /var/www/levineuwirth.org;
|
|
# ...
|
|
# include snippets/security-headers.conf;
|
|
# include snippets/static-assets.conf;
|
|
# include snippets/popup-proxy.conf;
|
|
# }
|
|
|
|
# Hide the nginx version from error pages and the Server header.
|
|
server_tokens off;
|
|
|
|
# HSTS — one year, with subdomains, preload-eligible. Only safe to
|
|
# enable once HTTPS is the only listener (the :80 vhost should already
|
|
# 301 → https). Once preload is requested via hstspreload.org, the
|
|
# max-age cannot be lowered without removing from the list manually.
|
|
add_header Strict-Transport-Security
|
|
"max-age=31536000; includeSubDomains; preload" always;
|
|
|
|
# Block MIME-sniffing — required for safe text/plain and svg responses.
|
|
add_header X-Content-Type-Options "nosniff" always;
|
|
|
|
# Defense against clickjacking. Modern browsers honor CSP frame-ancestors
|
|
# (set below); X-Frame-Options is kept for legacy clients.
|
|
add_header X-Frame-Options "DENY" always;
|
|
|
|
# Strip the Referer header to "scheme + host" on cross-origin requests.
|
|
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
|
|
|
# Default-deny powerful APIs. interest-cohort opts out of FLoC/Topics.
|
|
add_header Permissions-Policy
|
|
"camera=(), microphone=(), geolocation=(), interest-cohort=()" always;
|
|
|
|
# Content Security Policy. Shipped in Report-Only mode initially —
|
|
# promote to enforcing (strip the "-Report-Only" suffix) once the
|
|
# report stream has been clean for a week.
|
|
#
|
|
# External origins justified inline:
|
|
# cdn.jsdelivr.net KaTeX CSS + JS, Vega / Vega-Lite / Vega-Embed
|
|
# *.basemaps.cartocdn.com Leaflet basemap tiles (photography map only)
|
|
#
|
|
# Why 'unsafe-inline' on style:
|
|
# - photography.html emits <span style="background:$swatch$"> for
|
|
# palette swatches (data-driven, can't be hashed).
|
|
# - KaTeX adds inline styles when rendering math at runtime.
|
|
#
|
|
# Why 'unsafe-eval' on script:
|
|
# - vega-embed compiles Vega-Lite specs at runtime via new Function().
|
|
# Removing this would require pre-compiling specs at build time.
|
|
#
|
|
# To collect violation reports, set up a `report-uri` endpoint and add
|
|
# `report-uri /csp-report;` (and/or `report-to <group>;`) below.
|
|
add_header Content-Security-Policy-Report-Only
|
|
"default-src 'self'; \
|
|
script-src 'self' 'unsafe-eval' https://cdn.jsdelivr.net; \
|
|
style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net; \
|
|
img-src 'self' data: https://*.basemaps.cartocdn.com; \
|
|
font-src 'self' data:; \
|
|
connect-src 'self'; \
|
|
frame-ancestors 'none'; \
|
|
base-uri 'self'; \
|
|
form-action 'self'; \
|
|
object-src 'none'; \
|
|
upgrade-insecure-requests" always;
|