> ## Documentation Index
> Fetch the complete documentation index at: https://woku.app/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Security headers and CSP

> HSTS, nonce-based CSP, X-Frame-Options, Permissions-Policy and other headers applied by default

Every HTTP response from woku includes a set of security headers
calibrated to earn an A+ rating on
[securityheaders.com](https://securityheaders.com).

## Common headers (all domains)

| Header                       | Value                                                                  | Why                                                                              |
| ---------------------------- | ---------------------------------------------------------------------- | -------------------------------------------------------------------------------- |
| `Strict-Transport-Security`  | `max-age=63072000; includeSubDomains; preload`                         | Forces HTTPS for 2 years in the browser. Eligible for the HSTS preload list.     |
| `X-Content-Type-Options`     | `nosniff`                                                              | Blocks MIME sniffing.                                                            |
| `X-Frame-Options`            | `DENY`                                                                 | Blocks any framing of the content. Defense in depth on top of `frame-ancestors`. |
| `Referrer-Policy`            | `strict-origin-when-cross-origin`                                      | Does not leak path/query to external sites.                                      |
| `Permissions-Policy`         | `camera=(self), microphone=(self), geolocation=(), interest-cohort=()` | Enables camera/microphone only for woku; blocks geolocation and FLoC.            |
| `Cross-Origin-Opener-Policy` | `same-origin`                                                          | Isolates the browsing context to mitigate Spectre.                               |

## API (`api.woku.app`)

The API also serves the Swagger documentation at `/documentation`,
which uses its own inline scripts. On the API, all of the headers
above are applied and **CSP is not enforced** because the API is not
an HTML surface for users. CSP protection is enforced on the
frontends where code that the browser executes runs (review,
admin).

CORS is restricted to an **allowlist** (`ALLOWED_ORIGINS` env
var). In development, `localhost:5173` (Vite admin) and
`localhost:3000` (Next.js review) are added automatically.

## Public frontend (`review.woku.app`)

In addition to the common headers, this domain applies a **nonce-based
CSP** generated per request:

```
default-src 'self';
script-src 'self' 'nonce-<random>' 'strict-dynamic';
style-src 'self' 'unsafe-inline';
img-src 'self' blob: data: https://wokuapifiles.s3.us-east-1.amazonaws.com;
font-src 'self' data:;
connect-src 'self' https://api.woku.app wss://api.woku.app;
media-src 'self' blob: https://wokuapifiles.s3.us-east-1.amazonaws.com;
frame-ancestors 'none';
base-uri 'self';
form-action 'self';
object-src 'none';
upgrade-insecure-requests
```

The key points:

* **`script-src` with nonce + `strict-dynamic`**: only the
  Next.js bundle (which carries the nonce) and the scripts that this
  bundle loads dynamically are executed. Any `<script>` injected by an
  attacker (XSS) is blocked by the browser.
* **`frame-ancestors 'none'` + `object-src 'none'`**: nobody can
  embed woku in an `<iframe>` or load plugins. Defense against
  clickjacking.
* **`connect-src` limited**: the frontend can only make XHR/fetch to
  `api.woku.app` (HTTPS and WSS). Any exfiltration to other
  domains is blocked by the browser.
* **`upgrade-insecure-requests`**: if an `http://` resource is left in
  by mistake, the browser rewrites it to `https://`.

The nonce is generated with `crypto.getRandomValues(16 bytes)` encoded
in base64. It is **unique per request** and the browser rejects scripts
that do not carry it.

## Validation

We periodically test the three domains against:

* [securityheaders.com](https://securityheaders.com) → target
  sustained **A+**.
* [Mozilla Observatory](https://observatory.mozilla.org) → target
  sustained **A+**.
* [Hardenize](https://www.hardenize.com) → full battery
  (TLS, CSP, HTTPS, HSTS, redirects, certs).

## Reporting a downgrade

If you find a woku domain with headers more permissive than those
documented here: `team@woku.app`.
