Explorar el Código

fix: add COOP / CORP / Cross-Domain-Policies headers (SEC_REVIEW F59)

Both Caddyfiles emitted the M14 baseline (X-Content-Type-Options,
X-Frame-Options, Referrer-Policy, narrow Permissions-Policy) but
nothing from the modern cross-origin isolation cluster the
SEC_REVIEW called out.

Add to ui and api Caddyfile `header { … }` blocks:

  - `Cross-Origin-Opener-Policy: same-origin` — isolates the
    browsing context from any popups. A
    `window.opener.location = …` from a newly-spawned cross-origin
    tab can no longer reach back into the app.
  - `Cross-Origin-Resource-Policy: same-origin` — the resource may
    only be loaded by same-origin documents. Defeats cross-origin
    `<img>` / `<script>` / `<link>` sub-resource leaks; defence-in-
    depth on top of CORS for the api JSON.
  - `X-Permitted-Cross-Domain-Policies: none` — blocks legacy
    Adobe Flash / Acrobat `crossdomain.xml` lookups.

COEP `require-corp` was deliberately NOT added: it requires every
cross-origin resource (e.g. the jsDelivr-hosted RapiDoc on
/api/docs) to opt in via its own CORP header, which we don't
control on the CDN. The SEC_REVIEW called out COOP / CORP /
X-Permitted-CDP only — sticking to that scope. The
Permissions-Policy hardening called out separately (F61) is
tracked under its own finding.

Caddyfile syntax validated with `frankenphp validate --config …
--adapter caddyfile` on both files; both report "Valid
configuration".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
chiappa hace 3 días
padre
commit
206db1e492
Se han modificado 2 ficheros con 29 adiciones y 0 borrados
  1. 11 0
      api/docker/Caddyfile
  2. 18 0
      ui/docker/Caddyfile

+ 11 - 0
api/docker/Caddyfile

@@ -41,6 +41,17 @@
         X-Frame-Options "SAMEORIGIN"
         Referrer-Policy "strict-origin-when-cross-origin"
         Permissions-Policy "geolocation=(), microphone=(), camera=()"
+        # SEC_REVIEW F59: modern cross-origin isolation headers.
+        # - COOP `same-origin` isolates the docs viewer / any
+        #   future api-rendered page from cross-origin popups.
+        # - CORP `same-origin` blocks external pages from loading
+        #   the api JSON via cross-origin <script>/<img>/<link>
+        #   tags (defence in depth; CORS already gates fetch).
+        # - X-Permitted-Cross-Domain-Policies `none` blocks legacy
+        #   Adobe Flash / Acrobat cross-domain.xml lookups.
+        Cross-Origin-Opener-Policy "same-origin"
+        Cross-Origin-Resource-Policy "same-origin"
+        X-Permitted-Cross-Domain-Policies "none"
     }
 
     # HSTS: prod-only. Setting it in dev would lock you out of plain-HTTP

+ 18 - 0
ui/docker/Caddyfile

@@ -25,6 +25,24 @@
         X-Frame-Options "DENY"
         Referrer-Policy "strict-origin-when-cross-origin"
         Permissions-Policy "geolocation=(), microphone=(), camera=()"
+        # 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
+        #   newly-spawned cross-origin tab can no longer reach back.
+        # - CORP `same-origin` tells the browser this resource may
+        #   only be loaded by same-origin documents (defeats sub-
+        #   resource leaks via cross-origin <img>/<script>/<link>
+        #   inclusion).
+        # - X-Permitted-Cross-Domain-Policies `none` blocks legacy
+        #   Adobe Flash / Acrobat cross-domain.xml lookups.
+        # COEP `require-corp` is deliberately NOT set — that requires
+        # every cross-origin resource (e.g. the jsDelivr-hosted
+        # RapiDoc on /api/docs) to opt in via CORP, which we don't
+        # control. We're only after the COOP/CORP/legacy-Flash
+        # benefits the SEC_REVIEW called out.
+        Cross-Origin-Opener-Policy "same-origin"
+        Cross-Origin-Resource-Policy "same-origin"
+        X-Permitted-Cross-Domain-Policies "none"
     }
 
     @prod expression `{env.APP_ENV} == "production"`