Ensure location is safe before redirecting in Rails 7.0

When you access a Rails controller from another page, the originating URL is sent to the server as the referrer. In previous versions of Rails, the redirect_back query parameter with allow_other_host set as true could allow a vulnerability for an attacker to override this parameter and force the user to a malicious page.

Before Rails 7.0, the most common solution to this was to set the allow_other_host to false.

1
2
3
4
5
# This will redirect back to the source page
redirect_back(fallback_path: "/")

# This will not redirect back to the source page
redirect_back(fallback_path: "/", allow_other_host: false)

However, there still was a need to raise errors on unpermitted open redirects. With the Rails 7.0 ability to identify if the URL is internal and safe to redirect, the chance of compromising the referrer has become low. This works best for authentication, as in previous versions a compromised params[:return_to] could have led users to unsafe locations and provoked a credentials breach.

In Rails 7.0 the problem is solved by setting a url_from method in private:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class PostsController < ApplicationController
  def create
    @post = Post.new(post_params)
    if @post.save
      redirect_to return_url
    else
      render :new, status: :unprocessable_entity
    end
  end

  private
    def return_url
      url_from(params[:return_to]) || @post
    end

    def post_params
      params.require(:post).permit(:title, :body)
    end
end

The url_from method is new in Rails 7 and should not be confused with url_for which generates an internal URL from within the app.