Host permissions on redirect and apps with subdomains

Hello,

Since Rails 7.0, unpermitted open redirects raise an ActionController::Redirecting::UnsafeRedirectError by default. For most applications running under a single domain, it’s a neat addition. But what about applications that use lots of subdomains (ex: based on user names / organisations / projects / etc.), need to redirect users across them and may not be able to add allow_other_host: true on each call to redirect_to? (ex: when using controllers bundled in a gem, say Devise).

Open redirects permissions can be turned off but there is currently no way to get benefits of it for more than one hostname (as long as you know these domains are all under your control).

Rails applications already have an hosts config, used to configure the ActionDispatch::HostAuthorization middleware with allowed host names. Do you think this could be reused (when configured) in ActionController::Redirecting#_url_host_allowed? to check redirect location not only against request.host? Or is there a better way to prevent widely open redirects while still being able to redirect across controlled (sub)domains?


A naive implementation in any ApplicationController could look like this:

class ApplicationController
  private

  # Redefine a private and undocumented method, subject to changes in any future release!
  def _url_host_allowed?(url)
    return true if super

    host_with_port = URI(url.to_s).authority
    permissions = ActionDispatch::HostAuthorization::Permissions.new(Rails.application.config.hosts)
    permissions.allows?(host_with_port)
  rescue ArgumentError, URI::Error
    false
  end
end