package middleware import "net/http" // Security response headers. const ( // hstsValue is served even where TLS terminates at a reverse // proxy, so the browser enforces HTTPS end to end. Off when // config.HSTS is false (development), because pinning a // developer's browser to HTTPS on localhost is a self-inflicted // outage that outlives the process. hstsValue = "max-age=31536000; includeSubDomains" // cspValue is the baseline. Every template ships with external CSS // and no inline script, style or event handler, so nothing needs // 'unsafe-inline' and nothing should be given it: the moment a // project seeded from this template adds 'unsafe-inline', the // policy stops being a defence against injected script and becomes // decoration. cspValue = "default-src 'self'; " + "base-uri 'self'; " + "form-action 'self'; " + "frame-ancestors 'none'; " + "object-src 'none'" // permissionsPolicyValue denies the browser features this // application does not use. permissionsPolicyValue = "accelerometer=(), autoplay=(), camera=(), " + "display-capture=(), encrypted-media=(), geolocation=(), " + "gyroscope=(), magnetometer=(), microphone=(), midi=(), " + "payment=(), picture-in-picture=(), " + "publickey-credentials-get=(), screen-wake-lock=(), usb=(), " + "xr-spatial-tracking=()" referrerPolicyValue = "strict-origin-when-cross-origin" frameOptionsValue = "DENY" contentTypeOptsVal = "nosniff" ) // SecurityHeaders sets the response security headers before the handler // runs, so they are on every response the router produces — 404s, // handler error bodies, static assets, and the bare 500 the panic // recoverer writes. // // X-Frame-Options duplicates the CSP frame-ancestors directive on // purpose, for browsers that do not implement the latter. func (m *Middleware) SecurityHeaders() func(http.Handler) http.Handler { hsts := m.cfg.HSTS return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { h := w.Header() if hsts { h.Set("Strict-Transport-Security", hstsValue) } h.Set("Content-Security-Policy", cspValue) h.Set("X-Frame-Options", frameOptionsValue) h.Set("X-Content-Type-Options", contentTypeOptsVal) h.Set("Referrer-Policy", referrerPolicyValue) h.Set("Permissions-Policy", permissionsPolicyValue) next.ServeHTTP(w, r) }) } }