diff --git a/backend/app/services/ntfy.py b/backend/app/services/ntfy.py index 3fb4f2b..d1574ab 100644 --- a/backend/app/services/ntfy.py +++ b/backend/app/services/ntfy.py @@ -21,7 +21,8 @@ NTFY_TIMEOUT = 8.0 # seconds — hard cap to prevent hung requests # SSRF against Docker-internal services. If a self-hosted ntfy server on the LAN # is required, remove the RFC 1918 entries from _BLOCKED_NETWORKS and document the accepted risk. _BLOCKED_NETWORKS = [ - ipaddress.ip_network("127.0.0.0/8"), # IPv4 loopback + ipaddress.ip_network("0.0.0.0/8"), # "This network" — 0.0.0.0 maps to localhost on Linux + ipaddress.ip_network("127.0.0.0/8"), # IPv4 loopback ipaddress.ip_network("10.0.0.0/8"), # RFC 1918 private ipaddress.ip_network("172.16.0.0/12"), # RFC 1918 private — covers Docker bridge 172.17-31.x ipaddress.ip_network("192.168.0.0/16"), # RFC 1918 private diff --git a/frontend/nginx.conf b/frontend/nginx.conf index bae1954..17a0f09 100644 --- a/frontend/nginx.conf +++ b/frontend/nginx.conf @@ -103,6 +103,14 @@ server { # PT-L01: Prevent browser caching of authenticated API responses add_header Cache-Control "no-store, no-cache, must-revalidate" always; + # Security headers (must be repeated — nginx add_header in a location block + # overrides server-level add_header directives, so all headers must be explicit) + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-Content-Type-Options "nosniff" always; + add_header Referrer-Policy "strict-origin-when-cross-origin" always; + add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; img-src 'self' data:; font-src 'self' https://fonts.gstatic.com; connect-src 'self';" always; + add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; + add_header Permissions-Policy "camera=(), microphone=(), geolocation=(), interest-cohort=()" always; } # SPA fallback - serve index.html for all routes