Pārlūkot izejas kodu

fix: extend Permissions-Policy deny-list to full hardening (SEC_REVIEW F61)

The M14 starter Permissions-Policy denied only `geolocation`,
`microphone`, and `camera`. Every other modern feature
(accelerometer, ambient-light-sensor, payment, USB, MIDI,
clipboard-read, screen-wake-lock, idle-detection, web-share,
xr-spatial-tracking, the FLoC `interest-cohort`, etc.) was
implicitly allowed at the browser default — useful neither to the
admin UI nor to the API JSON, and a defence-in-depth gap a stored
XSS could exploit to fingerprint or exfiltrate via sensors / web-
share.

Replace with a comprehensive deny-list. Both Caddyfiles deny:
accelerometer, ambient-light-sensor, autoplay, battery, bluetooth,
camera, clipboard-read, display-capture, encrypted-media,
fullscreen, gamepad, geolocation, gyroscope, hid, idle-detection,
interest-cohort, magnetometer, microphone, midi, payment,
picture-in-picture, screen-wake-lock, serial, speaker-selection,
usb, web-share, xr-spatial-tracking.

`clipboard-write` is left at its same-origin default on the UI
Caddyfile so the existing `rawTokenCopy` Alpine component on the
Tokens page can still write the freshly-issued raw token to the
clipboard. The api Caddyfile denies `clipboard-write` outright
because the api never serves a page that needs it.

Both Caddyfiles validated with
`frankenphp validate --adapter caddyfile -e APP_ENV=production`;
both report "Valid configuration".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
chiappa 3 dienas atpakaļ
vecāks
revīzija
3556cd1920
2 mainītis faili ar 15 papildinājumiem un 2 dzēšanām
  1. 7 1
      api/docker/Caddyfile
  2. 8 1
      ui/docker/Caddyfile

+ 7 - 1
api/docker/Caddyfile

@@ -40,7 +40,13 @@
         # that still allows future same-origin embedding.
         X-Frame-Options "SAMEORIGIN"
         Referrer-Policy "strict-origin-when-cross-origin"
-        Permissions-Policy "geolocation=(), microphone=(), camera=()"
+        # SEC_REVIEW F61: extended deny-list for browser features the
+        # api never serves. Aligned with the ui Caddyfile so a browser
+        # loading a doc page (RapiDoc viewer) sees the same hardening.
+        # The api doesn't use clipboard-write so it stays denied here
+        # too (the ui keeps it on its same-origin default for the
+        # "copy raw token" button).
+        Permissions-Policy "accelerometer=(), ambient-light-sensor=(), autoplay=(), battery=(), bluetooth=(), camera=(), clipboard-read=(), clipboard-write=(), display-capture=(), encrypted-media=(), fullscreen=(), gamepad=(), geolocation=(), gyroscope=(), hid=(), idle-detection=(), interest-cohort=(), magnetometer=(), microphone=(), midi=(), payment=(), picture-in-picture=(), screen-wake-lock=(), serial=(), speaker-selection=(), usb=(), web-share=(), xr-spatial-tracking=()"
         # SEC_REVIEW F59: modern cross-origin isolation headers.
         # - COOP `same-origin` isolates the docs viewer / any
         #   future api-rendered page from cross-origin popups.

+ 8 - 1
ui/docker/Caddyfile

@@ -24,7 +24,14 @@
         X-Content-Type-Options "nosniff"
         X-Frame-Options "DENY"
         Referrer-Policy "strict-origin-when-cross-origin"
-        Permissions-Policy "geolocation=(), microphone=(), camera=()"
+        # SEC_REVIEW F61: extended deny-list for browser features
+        # the admin UI never uses. The narrow `geolocation=(),
+        # microphone=(), camera=()` was the M14 starter; this is the
+        # full hardening list. `clipboard-read` is blocked but
+        # `clipboard-write` is left at its same-origin default so
+        # the "copy raw token" button (rawTokenCopy Alpine
+        # component) still works on the Tokens page.
+        Permissions-Policy "accelerometer=(), ambient-light-sensor=(), autoplay=(), battery=(), bluetooth=(), camera=(), clipboard-read=(), display-capture=(), encrypted-media=(), fullscreen=(), gamepad=(), geolocation=(), gyroscope=(), hid=(), idle-detection=(), interest-cohort=(), magnetometer=(), microphone=(), midi=(), payment=(), picture-in-picture=(), screen-wake-lock=(), serial=(), speaker-selection=(), usb=(), web-share=(), xr-spatial-tracking=()"
         # SEC_REVIEW F59: modern cross-origin isolation headers.
         # - COOP `same-origin` isolates the browsing context from any
         #   popups it opens; a `window.opener.location = …` from a