Sikkerhed & CSP
Scope
frame-ancestors, iframe-sandbox og CORS-for-loader.js gælder kun embeddable widgets. Origin-isolation og immutable-caching gælder alle widgets på *.widget.greenbow.dk, inkl. standalone widgets som Checkout Return.
Origin-isolation
Hver widget har sit eget subdomæne ({slug}.widget.greenbow.dk). Det betyder:
- Cookies, localStorage, sessionStorage og IndexedDB er isoleret pr. widget. En kompromitteret widget kan ikke læse data fra en anden Greenbow widget.
- CSP og Permissions-Policy fungerer pr. origin — vi kan stramme policies pr. widget uden at påvirke andre.
X-Frame-Optionser deprecated og bruges ikke. Vi brugerContent-Security-Policy: frame-ancestorsi stedet.
Frame-ancestors
Hver widget tillader kun at blive iframet fra greenbow.dk og en hvidliste af godkendte partner-domæner:
add_header Content-Security-Policy
"frame-ancestors 'self' https://greenbow.dk https://*.greenbow.dk https://partner1.dk"
always;Listen vedligeholdes i nginx.conf.example (rod af repoet) og synces til DO App Platform pr. deploy.
Iframe sandbox
Loaderen sætter sandbox="allow-scripts allow-same-origin allow-popups allow-forms" på iframen. Det giver widgeten lov til:
- At køre scripts (nødvendigt — det er en SPA)
- At have sit eget origin (nødvendigt for cookies, fetch, storage)
- At åbne popups (f.eks. links til greenbow.dk)
- At submitte forms
Det blokerer eksplicit fra:
allow-top-navigation— widgeten kan ikke redirecte host-sidenallow-modals— widgeten kan ikke vise alert/confirm/prompt på host-sidenallow-pointer-lock,allow-orientation-lockosv.
CORS for loader.js
Loader-scriptet skal kunne loades fra alle partner-origins:
location = /loader.js {
add_header Access-Control-Allow-Origin "*" always;
add_header Cache-Control "public, max-age=300" always;
}Den korte cache (max-age=300) er bevidst — loaderen er den ene fil vi kan rette uden at deploye en ny widget-version. Hvis vi finder en bug i loader-logikken, ruller fixet ud globalt på 5 minutter.
Den faktiske app er immutable cached
Versionerede paths som /v1/, /v2/ cached i et år:
location ~ ^/v\d+/ {
add_header Cache-Control "public, max-age=31536000, immutable" always;
}