SECURITY: Remove ember-cli specific response from application routes (#15155)

Under some conditions, these varied responses could lead to cache poisoning, hence the 'security' label.

Previously the Rails application would serve JSON data in place of HTML whenever Ember CLI requested an `application.html.erb`-rendered page. This commit removes that logic, and instead parses the HTML out of the standard response. This means that Rails doesn't need to customize its response for Ember CLI.
This commit is contained in:
David Taylor
2021-12-01 16:10:40 +00:00
committed by GitHub
parent f37375f582
commit 1fa7a87f86
11 changed files with 265 additions and 77 deletions

View File

@ -119,23 +119,9 @@ class ApplicationController < ActionController::Base
class RenderEmpty < StandardError; end
class PluginDisabled < StandardError; end
class EmberCLIHijacked < StandardError; end
def catch_ember_cli_hijack
yield
rescue ActionView::Template::Error => ex
raise ex unless ex.cause.is_a?(EmberCLIHijacked)
send_ember_cli_bootstrap
end
rescue_from RenderEmpty do
catch_ember_cli_hijack do
with_resolved_locale { render 'default/empty' }
end
end
rescue_from EmberCLIHijacked do
send_ember_cli_bootstrap
with_resolved_locale { render 'default/empty' }
end
rescue_from ArgumentError do |e|
@ -324,21 +310,13 @@ class ApplicationController < ActionController::Base
rescue Discourse::InvalidAccess
return render plain: message, status: status_code
end
catch_ember_cli_hijack do
with_resolved_locale do
error_page_opts[:layout] = opts[:include_ember] ? 'application' : 'no_ember'
render html: build_not_found_page(error_page_opts)
end
with_resolved_locale do
error_page_opts[:layout] = opts[:include_ember] ? 'application' : 'no_ember'
render html: build_not_found_page(error_page_opts)
end
end
end
def send_ember_cli_bootstrap
response.headers['X-Discourse-Bootstrap-Required'] = true
response.headers['Content-Type'] = "application/json"
render json: { preloaded: @preloaded }
end
# If a controller requires a plugin, it will raise an exception if that plugin is
# disabled. This allows plugins to be disabled programmatically.
def self.requires_plugin(plugin_name)