From 04893444bdc286f557ee89d1cbda6828842fef2a Mon Sep 17 00:00:00 2001 From: Kim Pepper Date: Wed, 8 Apr 2026 12:46:40 +1000 Subject: [PATCH 1/2] Improve security headers based on headers.dev analysis - Migrate deprecated Feature-Policy to Permissions-Policy - Add Cross-Origin-Opener-Policy (same-origin-allow-popups) - Add Cross-Origin-Resource-Policy (same-site) - Add X-Permitted-Cross-Domain-Policies (none) - Extend error page CSP with base-uri and upgrade-insecure-requests Co-Authored-By: Claude Sonnet 4.6 --- .../nginx/conf.d/header/cross-origin-opener-policy.conf | 4 ++++ .../nginx/conf.d/header/cross-origin-resource-policy.conf | 4 ++++ base/etc/nginx/conf.d/header/feature.conf | 7 ++++--- .../conf.d/header/x-permitted-cross-domain-policies.conf | 3 +++ base/etc/nginx/conf.d/location/10-error-pages.conf | 2 +- 5 files changed, 16 insertions(+), 4 deletions(-) create mode 100644 base/etc/nginx/conf.d/header/cross-origin-opener-policy.conf create mode 100644 base/etc/nginx/conf.d/header/cross-origin-resource-policy.conf create mode 100644 base/etc/nginx/conf.d/header/x-permitted-cross-domain-policies.conf diff --git a/base/etc/nginx/conf.d/header/cross-origin-opener-policy.conf b/base/etc/nginx/conf.d/header/cross-origin-opener-policy.conf new file mode 100644 index 0000000..c867451 --- /dev/null +++ b/base/etc/nginx/conf.d/header/cross-origin-opener-policy.conf @@ -0,0 +1,4 @@ +# Cross-Origin-Opener-Policy prevents other origins from gaining a reference to this window. +# same-origin-allow-popups is used to preserve OAuth and payment popup flows. +# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy +add_header Cross-Origin-Opener-Policy "same-origin-allow-popups" always; diff --git a/base/etc/nginx/conf.d/header/cross-origin-resource-policy.conf b/base/etc/nginx/conf.d/header/cross-origin-resource-policy.conf new file mode 100644 index 0000000..c476f6c --- /dev/null +++ b/base/etc/nginx/conf.d/header/cross-origin-resource-policy.conf @@ -0,0 +1,4 @@ +# Cross-Origin-Resource-Policy controls which origins can include this resource. +# same-site allows subdomains on the same site (e.g. CDN serving from same eTLD+1). +# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Resource-Policy +add_header Cross-Origin-Resource-Policy "same-site" always; diff --git a/base/etc/nginx/conf.d/header/feature.conf b/base/etc/nginx/conf.d/header/feature.conf index c17010c..2fcf1d5 100644 --- a/base/etc/nginx/conf.d/header/feature.conf +++ b/base/etc/nginx/conf.d/header/feature.conf @@ -1,3 +1,4 @@ -# Feature Policy will allow a site to enable or disable certain browser features and APIs in the interest of better security and privacy. -# https://scotthelme.co.uk/a-new-security-header-feature-policy -add_header Feature-Policy "geolocation 'none'; midi 'none'; notifications 'none'; push 'none'; microphone 'none'; camera 'none'; magnetometer 'none'; gyroscope 'none'; speaker 'self'; vibrate 'none'; fullscreen 'self'; payment 'none';" always; +# Permissions-Policy controls which browser features and APIs are available to the page. +# Replaces the deprecated Feature-Policy header. +# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Permissions-Policy +add_header Permissions-Policy "geolocation=(), midi=(), notifications=(), push=(), microphone=(), camera=(), magnetometer=(), gyroscope=(), speaker=(self), vibrate=(), fullscreen=(self), payment=()" always; diff --git a/base/etc/nginx/conf.d/header/x-permitted-cross-domain-policies.conf b/base/etc/nginx/conf.d/header/x-permitted-cross-domain-policies.conf new file mode 100644 index 0000000..673cc8b --- /dev/null +++ b/base/etc/nginx/conf.d/header/x-permitted-cross-domain-policies.conf @@ -0,0 +1,3 @@ +# X-Permitted-Cross-Domain-Policies restricts Adobe Flash and PDF cross-domain data requests. +# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Permitted-Cross-Domain-Policies +add_header X-Permitted-Cross-Domain-Policies "none" always; diff --git a/base/etc/nginx/conf.d/location/10-error-pages.conf b/base/etc/nginx/conf.d/location/10-error-pages.conf index ca9c630..c29e135 100644 --- a/base/etc/nginx/conf.d/location/10-error-pages.conf +++ b/base/etc/nginx/conf.d/location/10-error-pages.conf @@ -2,7 +2,7 @@ location /error-pages/ { alias /etc/nginx/error-pages/; # Prevent scripts getting into our sub_filter. - add_header Content-Security-Policy "script-src 'none';"; + add_header Content-Security-Policy "script-src 'none'; base-uri 'none'; upgrade-insecure-requests;"; add_header X-Trace-ID $request_id; From baeb24b95ee0f11a28c96fc891cbbd60a8103566 Mon Sep 17 00:00:00 2001 From: Kim Pepper Date: Wed, 8 Apr 2026 16:06:59 +1000 Subject: [PATCH 2/2] Update tests: replace Feature-Policy with Permissions-Policy, add new header tests Co-Authored-By: Claude Sonnet 4.6 --- drupal/tests/test.go | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/drupal/tests/test.go b/drupal/tests/test.go index a5e4c2f..aecc1d1 100644 --- a/drupal/tests/test.go +++ b/drupal/tests/test.go @@ -23,9 +23,18 @@ func main() { // Test for header: Referrer-Policy. hasResponseHeader("http://127.0.0.1:8080", "Referrer-Policy"), hasResponseHeader("http://127.0.0.1:8080/index.PHP", "Referrer-Policy"), - // Test for header: Feature-Policy. - hasResponseHeader("http://127.0.0.1:8080", "Feature-Policy"), - hasResponseHeader("http://127.0.0.1:8080/index.PHP", "Feature-Policy"), + // Test for header: Permissions-Policy. + hasResponseHeader("http://127.0.0.1:8080", "Permissions-Policy"), + hasResponseHeader("http://127.0.0.1:8080/index.PHP", "Permissions-Policy"), + // Test for header: Cross-Origin-Opener-Policy. + hasResponseHeader("http://127.0.0.1:8080", "Cross-Origin-Opener-Policy"), + hasResponseHeader("http://127.0.0.1:8080/index.PHP", "Cross-Origin-Opener-Policy"), + // Test for header: Cross-Origin-Resource-Policy. + hasResponseHeader("http://127.0.0.1:8080", "Cross-Origin-Resource-Policy"), + hasResponseHeader("http://127.0.0.1:8080/index.PHP", "Cross-Origin-Resource-Policy"), + // Test for header: X-Permitted-Cross-Domain-Policies. + hasResponseHeader("http://127.0.0.1:8080", "X-Permitted-Cross-Domain-Policies"), + hasResponseHeader("http://127.0.0.1:8080/index.PHP", "X-Permitted-Cross-Domain-Policies"), // Test for header: Strict-Transport-Security. hasResponseHeader("http://127.0.0.1:8080", "Strict-Transport-Security"), hasResponseHeader("http://127.0.0.1:8080/foo", "Strict-Transport-Security"),