Skip to main content

Security

A+MDN HTTP Observatory grade. Re-run the scan yourself — the grade is reproducible from the response headers, nothing here is self-certified.

cookpit.org is a static site served over HTTPS with a strict set of response headers applied to every request. The headers are defined once in netlify.toml and reviewed in the open.

Response headers

HeaderValueWhat it does
Content-Security-Policydefault-src 'self'; script-src 'self' + SHA-256 hashes; object-src 'none'; base-uri 'self'; frame-ancestors 'self'The load-bearing header. script-src ships no 'unsafe-inline' — the two inline scripts Docusaurus emits are pinned by hash, so an injected <script> cannot run. object-src 'none' and base-uri 'self' close the usual bypasses.
Strict-Transport-Securitymax-age=63072000; includeSubDomains; preloadTwo-year HTTPS pin across every subdomain, preload-eligible. After the first visit the browser refuses to talk to cookpit.org over plain HTTP at all.
X-Content-Type-OptionsnosniffStops the browser from MIME-sniffing a response into something executable — a served .json or .md is treated as exactly its declared type.
Referrer-Policystrict-origin-when-cross-originSends the full URL on same-origin navigations but only the origin cross-site, and nothing at all when downgrading to HTTP. No path leakage to third parties.
Permissions-Policygeolocation=(), microphone=(), camera=(), payment=(), usb=(), interest-cohort=()Switches off powerful APIs the site never uses, and opts out of FLoC/Topics ad cohorting.
frame-ancestors (via CSP)'self'Clickjacking defence — the site can only be framed by itself. Supersedes the legacy X-Frame-Options header.

How the A+ is held in place

The single thing standing between a typical site and an A+ on the Observatory is 'unsafe-inline' in script-src — a 20-point penalty. We don't ship it. The two inline bootstrap scripts Docusaurus emits (the colour-mode initialiser on every page, and the base-URL fallback banner on the homepage) are pinned by their SHA-256 hashes instead.

Hash-pinning a generated site is brittle on its own: a framework upgrade can change an inline script's bytes, its hash drifts, and the browser silently refuses to run it — a white screen that a passing npm run build would not catch. So check-csp-hashes.mjs runs in CI after every build: it re-scans the built HTML for inline scripts and fails the pipeline if any one of them is not already allowed by the CSP. The grade cannot silently regress.

Scope

This covers the static site at cookpit.org. The validation and attestation service at validator.cookpit.org is a separate, narrowly-scoped HTTP service: it holds uploaded files in memory for the duration of a single request, never writes them to disk and never logs them, and accepts cross-origin requests only from the cookpit.org origins.

Authenticity of an individual cooking file is a separate, stronger guarantee carried by the file itself: every authenticated .A.jsonld is Ed25519-signed, so tampering is detectable by anyone, offline, without trusting this site. If you build an app that consumes cookpit files, see Trusted — verifying a file in your app for the one rule, the pinned public key, and a drop-in verifier.