Summary
Add a typed, immutable policy to Server.Config for security headers which should apply consistently to Roc responses, native file responses, probes, and host-generated errors.
Illustrative configuration:
security_headers: SecurityHeaders.policy({
content_type_options: Nosniff,
referrer_policy: StrictOriginWhenCrossOrigin,
frame_options: Deny,
opener_policy: Disabled,
hsts: Disabled,
})
The default must preserve current behavior: no security headers are enabled implicitly.
Why this belongs in the platform
Several browser security headers are easy to serialize incorrectly or omit from non-application responses. basic-webserver itself serves native files and native operational routes, so a helper applied only inside respond! cannot cover the entire server.
Django makes the same deployment observation: security headers are most effective at a layer that covers application and non-application responses.
An immutable startup policy is a better fit than a general middleware runtime. The host only applies prevalidated headers; it does not run application callbacks.
Initial scope
Typed support for:
X-Content-Type-Options: nosniff
Referrer-Policy
X-Frame-Options: DENY | SAMEORIGIN
Cross-Origin-Opener-Policy
Strict-Transport-Security, including max age, includeSubDomains, and preload
Rules:
- Header names are matched case-insensitively.
- A response's explicit value takes precedence over the global policy.
- The host must not emit duplicate managed headers accidentally.
- HSTS is opt-in, never inferred from
Forwarded or X-Forwarded-Proto, and prominently documented as a domain-wide deployment decision.
- HSTS should normally be configured at the public TLS-terminating proxy when one exists.
- Avoid deprecated or harmful headers such as HPKP and
Expect-CT.
- Do not claim that the policy makes an application "secure".
Content Security Policy is intentionally excluded initially. A useful CSP depends on the application's scripts, styles, framing, reporting, and nonce strategy; a generic preset is likely either ineffective or application-breaking.
Tests
- All response paths, including native files, probes, and generated errors.
- Case-insensitive conflict detection and per-response precedence.
- Exact serialization for every typed policy value.
- HSTS validation and disabled behavior.
- No duplicate headers across HTTP/1.1 and HTTP/2.
Acceptance criteria
References
Summary
Add a typed, immutable policy to
Server.Configfor security headers which should apply consistently to Roc responses, native file responses, probes, and host-generated errors.Illustrative configuration:
The default must preserve current behavior: no security headers are enabled implicitly.
Why this belongs in the platform
Several browser security headers are easy to serialize incorrectly or omit from non-application responses. basic-webserver itself serves native files and native operational routes, so a helper applied only inside
respond!cannot cover the entire server.Django makes the same deployment observation: security headers are most effective at a layer that covers application and non-application responses.
An immutable startup policy is a better fit than a general middleware runtime. The host only applies prevalidated headers; it does not run application callbacks.
Initial scope
Typed support for:
X-Content-Type-Options: nosniffReferrer-PolicyX-Frame-Options: DENY | SAMEORIGINCross-Origin-Opener-PolicyStrict-Transport-Security, including max age,includeSubDomains, andpreloadRules:
ForwardedorX-Forwarded-Proto, and prominently documented as a domain-wide deployment decision.Expect-CT.Content Security Policy is intentionally excluded initially. A useful CSP depends on the application's scripts, styles, framing, reporting, and nonce strategy; a generic preset is likely either ineffective or application-breaking.
Tests
Acceptance criteria
References