Skip to main content

Security headers in Skapp

Type: ExplanationCreated: Team: Security
draft

Overview​

Skapp sets its security headers at the Cloudflare edge (zone skapp.com), so they apply to every *.skapp.com host — web app, APIs, and all tenant subdomains — with no application changes. Seven headers are deployed at the edge, Content-Type comes from the application, two headers are intentionally skipped, and CSP is parked as future work. External grade: A.

What Skapp deploys​

HeaderValueNotes
Strict-Transport-Security(via HSTS toggle)See Cloudflare config below
X-Frame-OptionsDENY
X-Content-Type-Optionsnosniff
Referrer-Policystrict-origin-when-cross-origin
Permissions-Policycamera=(), microphone=(), geolocation=()
Cross-Origin-Opener-Policysame-origin
Cross-Origin-Resource-Policysame-siteChosen over same-origin because frontend (app.skapp.com) and API (app-api.skapp.com) are different subdomains
Content-Typeapplication/json; charset=utf-8 on JSONAlready set by the application (Spring Boot) — no edge change## What Skapp deliberately does not set- Content-Security-Policy (CSP) — parked (future work). Skapp loads scripts from many third parties (Google sign-in, Firebase, Hotjar, Sentry, reCAPTCHA, Google Analytics, and more), so a strict script-src allowlist would need updating per new integration. Plan when picked up: deploy Content-Security-Policy-Report-Only first, collect violations from real traffic, build the allowlist, then enforce.
  • Cross-Origin-Embedder-Policy (COEP) — skipped by design. Skapp doesn't use cross-origin isolation features; require-corp would break Google Fonts, S3/CloudFront assets, and third-party scripts for no benefit.
  • Clear-Site-Data — skipped by design. The "cookies" directive clears cookies for the whole skapp.com domain and all subdomains. Skapp intentionally lets one user hold concurrent sessions across multiple tenant subdomains, and logout from one tenant must not end the others. Session teardown is handled by tenant-scoped server-side invalidation instead.

Cloudflare configuration​

All in the skapp.com zone. Two places:

1. The six static headers — one Transform Rule​

Rules → Transform Rules → Modify Response Header → rule Security Headers – Tier 1.

  • Matches: All incoming requests — covers every *.skapp.com host including future tenant subdomains, nothing to maintain.
  • Operation: Set static per header (Set, not Add — avoids duplicates).
  • Headers: the six edge headers from the table above (X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy, COOP, CORP).
  • To change a value: edit the rule, update, Deploy (instant).
  • To exclude a subdomain (e.g. an embeddable surface that must not be X-Frame-Options: DENY): change the match to (http.host wildcard "*.skapp.com") and not (http.host eq "<host>").

Transform rules static headers

2. HSTS — separate toggle​

SSL/TLS → Edge Certificates → HTTP Strict Transport Security (HSTS) → Enabled.

  • Not part of the Transform Rule — it has its own control.
  • The preload directive is set, but the domain is NOT submitted to hstspreload.org. Don't submit until every *.skapp.com host is confirmed permanently HTTPS (removal is slow).

Not configured in Cloudflare​

  • CSP — when added, use a separate rule.
  • COEP — not added (intentional).
  • Clear-Site-Data — not added (intentional). If ever revisited, it must be a path-scoped rule on the logout endpoint only — never "All incoming requests."

Verify​

securityheaders.com or MDN Observatory on app.skapp.com → expect grade A. Or PowerShell:

powershell

$resp = Invoke-WebRequest -Uri "https://app.skapp.com/" -Method Head -UseBasicParsing
"x-frame-options","x-content-type-options","referrer-policy","permissions-policy",
"cross-origin-opener-policy","cross-origin-resource-policy","strict-transport-security" |
ForEach-Object {
if ($resp.Headers.Keys -contains $_) { Write-Host "PRESENT $_" -ForegroundColor Green }
else { Write-Host "MISSING $_" -ForegroundColor Red }
}

Run against app-api.skapp.com and a sample tenant subdomain too, to confirm zone-wide coverage.