Class: Tina4::SecurityHeadersMiddleware
- Inherits:
-
Object
- Object
- Tina4::SecurityHeadersMiddleware
- Defined in:
- lib/tina4/middleware.rb
Overview
SecurityHeadersMiddleware -- injects security headers on every response. Config via env:
TINA4_FRAME_OPTIONS — X-Frame-Options (default: SAMEORIGIN)
TINA4_HSTS — Strict-Transport-Security max-age (default: "" = off)
TINA4_CSP — Content-Security-Policy (default: "default-src 'self'")
TINA4_REFERRER_POLICY — Referrer-Policy (default: strict-origin-when-cross-origin)
TINA4_PERMISSIONS_POLICY — Permissions-Policy (default: camera=(), microphone=(), geolocation=())
Class Method Summary collapse
-
.attach ⇒ Object
Register this middleware in the default chain (secure-by-default).
- .before_security(request, response) ⇒ Object
Class Method Details
.attach ⇒ Object
Register this middleware in the default chain (secure-by-default).
Unlike CSRF (opt-in via TINA4_CSRF) this is UNCONDITIONAL: a default app ships the security headers with no opt-in -- the SECHDR-DEC-01 posture that closes the SECHDR-OFF-BY-DEFAULT gap (the middleware existed with good defaults but was never registered). Idempotent (Middleware.use de-dupes). The framework calls it once at boot (Tina4.initialize!). Returns true.
787 788 789 790 |
# File 'lib/tina4/middleware.rb', line 787 def attach Tina4::Middleware.use(self) true end |
.before_security(request, response) ⇒ Object
792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 |
# File 'lib/tina4/middleware.rb', line 792 def before_security(request, response) response.headers["X-Frame-Options"] = ENV["TINA4_FRAME_OPTIONS"] || "SAMEORIGIN" response.headers["X-Content-Type-Options"] = "nosniff" # HSTS is HTTPS-only (SECHDR-DEC-02): a downgrade-protection header on a # plain-HTTP response is inert at best and ships a bad max-age on an # unencrypted scheme at worst. Emit it ONLY when TINA4_HSTS is set AND the # request is HTTPS -- Request.secure_scheme? honours x-forwarded-proto # (first hop) then rack.url_scheme, the same source of truth the session # cookie's Secure flag uses. Defensive env lookup keeps a non-Request from # turning every response into a 500 now that this runs on every request. hsts = ENV["TINA4_HSTS"] || "" env = request.respond_to?(:env) ? request.env : {} if !hsts.empty? && Tina4::Request.secure_scheme?(env) response.headers["Strict-Transport-Security"] = "max-age=#{hsts}; includeSubDomains" end response.headers["Content-Security-Policy"] = ENV["TINA4_CSP"] || "default-src 'self'" response.headers["Referrer-Policy"] = ENV["TINA4_REFERRER_POLICY"] || "strict-origin-when-cross-origin" response.headers["X-XSS-Protection"] = "0" response.headers["Permissions-Policy"] = ENV["TINA4_PERMISSIONS_POLICY"] || "camera=(), microphone=(), geolocation=()" [request, response] end |