class ActionDispatch::HostAuthorization
if config.consider_all_requests_local
is set to true, otherwise the body is empty.
responds with 403 Forbidden
. The body of the response contains debug info
The default response app logs blocked host info with level ‘error’ and
default one will run.
application will be executed and rendered. If no response_app
is given, a
When a request comes to an unauthorized host, the response_app
config.host_authorization = { exclude: ->(request) { request.path =~ /healthcheck/ } }
Requests can opt-out of Host Authorization with exclude
:config.host_authorization
.
the hosts a request can be sent to, and is passed the options set in
This middleware guards from DNS rebinding attacks by explicitly permitting
def authorized?(request)
def authorized?(request) origin_host = request.get_header("HTTP_HOST") forwarded_host = request.x_forwarded_host&.split(/,\s?/)&.last @permissions.allows?(origin_host) && (forwarded_host.blank? || @permissions.allows?(forwarded_host)) end
def call(env)
def call(env) return @app.call(env) if @permissions.empty? request = Request.new(env) if authorized?(request) || excluded?(request) mark_as_authorized(request) @app.call(env) else @response_app.call(env) end end
def excluded?(request)
def excluded?(request) @exclude && @exclude.call(request) end
def initialize(app, hosts, exclude: nil, response_app: nil)
def initialize(app, hosts, exclude: nil, response_app: nil) @app = app @permissions = Permissions.new(hosts) @exclude = exclude @response_app = response_app || DefaultResponseApp.new end
def mark_as_authorized(request)
def mark_as_authorized(request) request.set_header("action_dispatch.authorized_host", request.host) end