Class: Otto::Security::CSP::ReportMiddleware
- Inherits:
-
Object
- Object
- Otto::Security::CSP::ReportMiddleware
- Defined in:
- lib/otto/security/csp/report_middleware.rb
Overview
Rack middleware that receives browser-posted Content-Security-Policy violation reports and dispatches them to an application callback.
This is the receiving half of Otto’s CSP support; the emitting half is
Otto::Security::Config#generate_nonce_csp / Response#send_csp_headers
(and the static Otto::Security::Config#enable_csp!). When a report URI
is configured, the emitted policy carries a report-uri directive
pointing here.
Behavior (all mandatory for a public, unauthenticated receiver):
- INERT unless Otto::Security::Config#csp_report_uri is set. When it is not configured the middleware is a transparent pass-through.
- Only intercepts a POST whose path matches the configured report URI. Everything else (other paths, other methods) passes through untouched.
- Short-circuits BEFORE inner middleware, so CSRF, auth, and rate limiting never see the request. This is why browsers can POST reports with no CSRF token: the report never reaches the CSRF middleware. Otto::Security::Core#enable_csp_reporting! pins this middleware OUTERMOST (via the :outermost stack position), so the guarantee holds regardless of the order security features are enabled in. The flip side is that reports also bypass rate limiting — see the DoS note on Otto::Security::Core#enable_csp_reporting!; keep callbacks cheap.
- Enforces a hard MAX_BODY_BYTES body cap. Oversized bodies are
detected with a
cap + 1read and skipped WITHOUT parsing, so a hostile client cannot force large allocations against a public endpoint. - Parses both wire formats via Parser and invokes the registered callback once per normalized report.
- NEVER raises to the client and always responds
204 No Content(browsers ignore the body). A throwing callback is isolated by Otto::Security::Config#dispatch_csp_violation.
Constant Summary collapse
- MAX_BODY_BYTES =
Hard cap on the request body we are willing to read/parse. Browsers send small JSON documents; anything larger is abuse and is dropped.
64 * 1024
Instance Method Summary collapse
-
#call(env) ⇒ Object
-
#initialize(app, config = nil) ⇒ ReportMiddleware
constructor
64 KiB.
Constructor Details
#initialize(app, config = nil) ⇒ ReportMiddleware
64 KiB
46 47 48 49 |
# File 'lib/otto/security/csp/report_middleware.rb', line 46 def initialize(app, config = nil) @app = app @config = config || Otto::Security::Config.new end |
Instance Method Details
#call(env) ⇒ Object
51 52 53 54 55 |
# File 'lib/otto/security/csp/report_middleware.rb', line 51 def call(env) return @app.call(env) unless report_request?(env) receive_report(env) end |