Skip to content

Add an explicit global browser security-response-header policy #200

Description

@lukewilliamboswell

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

  • A startup policy can apply selected headers to every host-produced response.
  • Every policy is opt-in and typed.
  • Dynamic responses can override a managed header explicitly.
  • HSTS carries clear proxy, certificate, and whole-domain warnings.
  • CSP and deprecated security headers are not hidden inside a misleading preset.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions