From 263f281b30ac0f7daaf654e2e9abee71f9d80709 Mon Sep 17 00:00:00 2001 From: Christian Cleberg Date: Mon, 3 Aug 2026 12:03:54 -0500 Subject: fix security headers for new vhosts --- linux/nginx/etc/nginx/conf.d/i.conf | 13 +++++++++++++ linux/nginx/etc/nginx/conf.d/i.conf.bak-i-onion | 9 +++++++++ linux/nginx/etc/nginx/conf.d/krz.sh.conf | 1 + .../etc/nginx/custom.d/http/content_type_maps.conf | 21 +++++++++++++++++++-- .../security/content-security-policy-krz.conf | 10 ++++++++++ 5 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 linux/nginx/etc/nginx/conf.d/i.conf.bak-i-onion create mode 100644 linux/nginx/etc/nginx/custom.d/security/content-security-policy-krz.conf (limited to 'linux/nginx/etc') diff --git a/linux/nginx/etc/nginx/conf.d/i.conf b/linux/nginx/etc/nginx/conf.d/i.conf index 23cef0d..ab0d429 100644 --- a/linux/nginx/etc/nginx/conf.d/i.conf +++ b/linux/nginx/etc/nginx/conf.d/i.conf @@ -1,9 +1,22 @@ server { listen 127.0.0.1:10048; server_name i.krz.sh; + add_header Onion-Location "http://j42zbkbxrdx4mvkyutt7jiwpucgcmrdvaelwcwmgwn3mzus2v6x3toad.onion$request_uri" always; include custom.d/basic.conf; include custom.d/security/content-security-policy.conf; root /var/www/i/; autoindex on; location / { try_files $uri $uri/ =404; } } + +# Onion counterpart of i.krz.sh. Reached via tor -> 127.0.0.1:10049, so it +# never transits Cloudflare; nginx is the only thing setting headers here. +server { + listen 127.0.0.1:10049; + server_name j42zbkbxrdx4mvkyutt7jiwpucgcmrdvaelwcwmgwn3mzus2v6x3toad.onion; + include custom.d/basic.conf; + include custom.d/security/content-security-policy.conf; + root /var/www/i/; + autoindex on; + location / { try_files $uri $uri/ =404; } +} diff --git a/linux/nginx/etc/nginx/conf.d/i.conf.bak-i-onion b/linux/nginx/etc/nginx/conf.d/i.conf.bak-i-onion new file mode 100644 index 0000000..23cef0d --- /dev/null +++ b/linux/nginx/etc/nginx/conf.d/i.conf.bak-i-onion @@ -0,0 +1,9 @@ +server { + listen 127.0.0.1:10048; + server_name i.krz.sh; + include custom.d/basic.conf; + include custom.d/security/content-security-policy.conf; + root /var/www/i/; + autoindex on; + location / { try_files $uri $uri/ =404; } +} diff --git a/linux/nginx/etc/nginx/conf.d/krz.sh.conf b/linux/nginx/etc/nginx/conf.d/krz.sh.conf index 0169dbe..dcf5f62 100644 --- a/linux/nginx/etc/nginx/conf.d/krz.sh.conf +++ b/linux/nginx/etc/nginx/conf.d/krz.sh.conf @@ -4,5 +4,6 @@ server { root /var/www/krz.sh/; absolute_redirect off; include custom.d/basic.conf; + include custom.d/security/content-security-policy-krz.conf; location / { try_files $uri $uri/ =404; } } diff --git a/linux/nginx/etc/nginx/custom.d/http/content_type_maps.conf b/linux/nginx/etc/nginx/custom.d/http/content_type_maps.conf index ee53aed..b27cbf0 100644 --- a/linux/nginx/etc/nginx/custom.d/http/content_type_maps.conf +++ b/linux/nginx/etc/nginx/custom.d/http/content_type_maps.conf @@ -50,7 +50,7 @@ map $sent_http_content_type $x_frame_options { # literal newlines, which nginx emitted verbatim -- a folded, malformed header # that clients saw as empty. Policies must be ONE line. map $sent_http_content_type $content_security_policy { - ~*text/(html|javascript)|application/pdf|xml "default-src 'self'; img-src 'self' data:; base-uri 'none'; form-action 'self'; frame-ancestors 'none'; object-src 'none'; upgrade-insecure-requests"; + ~*text/(html|javascript)|application/pdf|xml "default-src 'self'; img-src 'self' data:; base-uri 'none'; form-action 'self'; frame-ancestors 'none'; object-src 'none'"; } # cleberg.* only. Mirrors what the site actually loads, verified by grepping @@ -69,6 +69,23 @@ map $sent_http_content_type $content_security_policy_cmc { ~*text/(html|javascript)|application/pdf|xml "default-src 'self'; img-src 'self' https://img.cleberg.net data:; script-src 'self' https://bubbles.town; connect-src 'self' https://bubbles.town; style-src 'self' https://cleberg.net; font-src 'self' https://cleberg.net; base-uri 'none'; form-action 'self'; frame-ancestors 'none'; object-src 'none'"; } +# krz.sh only. Derived from the served HTML after the img.cleberg.net removal +# (2026-08-03), counted with an HTML parser: +# 14 -> https://i.krz.sh (the new krz-side image host) +# 12 -> https://krz.sh (ABSOLUTE, not relative) +# 12 -> https://krz.sh (covered by img-src) +# 0 scripts, inline or external; 0 inline styles. +# +# `https://krz.sh` is listed explicitly because those URLs are absolute: on a +# future krz.sh onion they would be cross-origin and 'self' would block them. +# Same reasoning as the cmc policy above. +# +# script-src stays 'self' rather than 'none': the site ships no scripts today, +# but 'none' would break the first one added, in a way that is easy to misread. +map $sent_http_content_type $content_security_policy_krz { + ~*text/(html|javascript)|application/pdf|xml "default-src 'self'; img-src 'self' https://krz.sh https://i.krz.sh data:; style-src 'self' https://krz.sh; font-src 'self' https://krz.sh; script-src 'self'; base-uri 'none'; form-action 'self'; frame-ancestors 'none'; object-src 'none'"; +} + # For apps that ship inline