Response headers
The always-on set, the content security policy, and HSTS.
Applied to every response unless a handler has already set them:
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
X-Frame-Options: DENY
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Resource-Policy: same-originContent-Security-Policy
CSP is applied to HTML responses only, defaulting to a 'self' policy with object-src 'none' and frame-ancestors 'none'. Override it with security.csp.
This wiki ships:
csp = "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; font-src 'self'; connect-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'"Note what is absent: 'unsafe-inline'. Islands do not need it. The client runtime is an external module script, island props travel as HTML attributes rather than inline <script> blocks, and the stylesheet is an external file. A policy with 'unsafe-inline' in script-src is close to no script policy at all, so it is worth checking whether your own pages actually need it before adding it.
A headless JSON service should tighten the policy rather than inherit the HTML one:
csp = "default-src 'none'; frame-ancestors 'none'"HSTS
Strict-Transport-Security is sent only when security.hsts_seconds is above zero and the request arrived over TLS, determined from X-Forwarded-Proto. That header is meaningful only behind a proxy that overwrites it — see deployment.
Escaping and injection
MarkupBuilder escapes &, <, >, " and ' in text and attribute values, and validates tag and attribute names. raw is the single unescaped path in the entire rendering layer, which makes "who calls raw?" an answerable audit question.
JsonBuilder escapes the mandatory set plus U+2028 and U+2029.
Response header names and values are validated at write time, not on the way in, so a handler cannot inject a header or split a response no matter where its strings came from.
Cookies
setCookie defaults to HttpOnly, Secure and SameSite=Lax.
A cookie that a client-side island must read — a display preference, for instance — cannot be HttpOnly, and that is a deliberate exception worth making explicitly rather than by default. Keep such cookies free of anything that matters, and validate their contents on the server against a fixed set of expected values.