Skip to content

Commit

Permalink
Use safe redirect paths in admin redirects
Browse files Browse the repository at this point in the history
This makes sure all redirects we do in the admin via do_redirect_to uses a safe redirect url.

(cherry picked from commit 7adefce)
tvdeyen committed Jan 7, 2025

Verified

This commit was signed with the committer’s verified signature.
tvdeyen Thomas von Deyen
1 parent 6b075b7 commit 6a0cbde
Showing 5 changed files with 20 additions and 10 deletions.
13 changes: 11 additions & 2 deletions app/controllers/alchemy/admin/base_controller.rb
Original file line number Diff line number Diff line change
@@ -46,6 +46,12 @@ def is_safe_redirect_path?(path)
path.to_s.match? %r{^#{mount_path}admin/}
end

def relative_referer_path(referer = request.referer)
return unless referer

URI(referer).path
end

# Disable layout rendering for xhr requests.
def set_layout
request.xhr? ? false : "alchemy/admin"
@@ -122,13 +128,16 @@ def render_errors_or_redirect(object, redirect_url, flash_notice)

# Does redirects for html and js requests
#
# Makes sure that the redirect path is safe.
#
def do_redirect_to(url_or_path)
redirect_path = safe_redirect_path(url_or_path)
respond_to do |format|
format.js {
@redirect_url = url_or_path
@redirect_url = redirect_path
render :redirect
}
format.html { redirect_to url_or_path }
format.html { redirect_to redirect_path }
end
end

2 changes: 1 addition & 1 deletion app/controllers/alchemy/admin/languages_controller.rb
Original file line number Diff line number Diff line change
@@ -40,7 +40,7 @@ def destroy
def switch
@language = set_alchemy_language(params[:language_id])
session[:alchemy_language_id] = @language.id
do_redirect_to request.referer || alchemy.admin_dashboard_path
do_redirect_to relative_referer_path || alchemy.admin_dashboard_path
end

private
9 changes: 5 additions & 4 deletions app/controllers/alchemy/admin/pages_controller.rb
Original file line number Diff line number Diff line change
@@ -183,14 +183,15 @@ def unlock
respond_to do |format|
format.js
format.html do
redirect_to(
params[:redirect_to].presence || admin_pages_path,
allow_other_host: true
)
redirect_to(unlock_redirect_path, allow_other_host: true)
end
end
end

def unlock_redirect_path
safe_redirect_path(fallback: admin_pages_path)
end

# Sets the page public and updates the published_at attribute that is used as cache_key
#
def publish
2 changes: 1 addition & 1 deletion app/controllers/alchemy/admin/resources_controller.rb
Original file line number Diff line number Diff line change
@@ -78,7 +78,7 @@ def destroy
flash[:error] = resource_instance_variable.errors.full_messages.join(", ")
end
flash_notice_for_resource_action
do_redirect_to resource_url_proxy.url_for(search_filter_params.merge(action: "index"))
do_redirect_to resource_url_proxy.url_for(search_filter_params.merge(action: "index", only_path: true))
end

def resource_handler
4 changes: 2 additions & 2 deletions spec/requests/alchemy/admin/pages_controller_spec.rb
Original file line number Diff line number Diff line change
@@ -683,10 +683,10 @@ module Alchemy
end

context "if passing :redirect_to through params" do
subject { post unlock_admin_page_path(page, redirect_to: "this/path") }
subject { post unlock_admin_page_path(page, redirect_to: "/admin/path") }

it "should redirect to the given path" do
is_expected.to redirect_to("this/path")
is_expected.to redirect_to("/admin/path")
end
end
end

0 comments on commit 6a0cbde

Please sign in to comment.