Skip to content

Commit 0915a3e

Browse files
authored
Merge pull request rails#49858 from skipkayhil/hm-dont-assign-internal-variables
Prevent assigning internal ivars to AV::Base
2 parents 759ae90 + 24213d6 commit 0915a3e

File tree

4 files changed

+35
-6
lines changed

4 files changed

+35
-6
lines changed

actionpack/lib/action_controller/base.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@ def self.without_modules(*modules)
247247
PROTECTED_IVARS = AbstractController::Rendering::DEFAULT_PROTECTED_INSTANCE_VARIABLES + %i(
248248
@_params @_response @_request @_config @_url_options @_action_has_layout @_view_context_class
249249
@_view_renderer @_lookup_context @_routes @_view_runtime @_db_runtime @_helper_proxy
250+
@_marked_for_same_origin_verification @_rendered_format
250251
)
251252

252253
def _protected_ivars

actionpack/lib/action_controller/metal/request_forgery_protection.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ def reset(request)
340340

341341
def initialize(...)
342342
super
343-
@marked_for_same_origin_verification = nil
343+
@_marked_for_same_origin_verification = nil
344344
end
345345

346346
def reset_csrf_token(request) # :doc:
@@ -414,13 +414,13 @@ def verify_same_origin_request # :doc:
414414

415415
# GET requests are checked for cross-origin JavaScript after rendering.
416416
def mark_for_same_origin_verification! # :doc:
417-
@marked_for_same_origin_verification = request.get?
417+
@_marked_for_same_origin_verification = request.get?
418418
end
419419

420420
# If the +verify_authenticity_token+ before_action ran, verify that
421421
# JavaScript responses are only served to same-origin GET requests.
422422
def marked_for_same_origin_verification? # :doc:
423-
@marked_for_same_origin_verification ||= false
423+
@_marked_for_same_origin_verification ||= false
424424
end
425425

426426
# Check for cross-origin JavaScript responses.

actionview/lib/action_view/rendering.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ module Rendering
2727
extend ActiveSupport::Concern
2828
include ActionView::ViewPaths
2929

30-
attr_reader :rendered_format
30+
attr_internal_reader :rendered_format
3131

3232
def initialize
33-
@rendered_format = nil
33+
@_rendered_format = nil
3434
super
3535
end
3636

@@ -136,7 +136,7 @@ def _render_template(options)
136136
end
137137

138138
rendered_format = rendered_template.format || lookup_context.formats.first
139-
@rendered_format = Template::Types[rendered_format]
139+
@_rendered_format = Template::Types[rendered_format]
140140

141141
rendered_template.body
142142
end

actionview/test/actionpack/controller/render_test.rb

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,10 @@ def hello_world_with_layout_false
126126
render layout: false
127127
end
128128

129+
def render_instance_variables
130+
render inline: "<%= instance_variables.sort %>"
131+
end
132+
129133
# :ported:
130134
def render_template_with_instance_variables
131135
@secret = "in the sauce"
@@ -721,6 +725,7 @@ class RenderTest < ActionController::TestCase
721725
get :render_hello_world_with_forward_slash, to: "test#render_hello_world_with_forward_slash"
722726
get :render_implicit_html_template_from_xhr_request, to: "test#render_implicit_html_template_from_xhr_request"
723727
get :render_implicit_js_template_without_layout, to: "test#render_implicit_js_template_without_layout"
728+
get :render_instance_variables, to: "test#render_instance_variables"
724729
get :render_line_offset, to: "test#render_line_offset"
725730
get :render_nothing_with_appendix, to: "test#render_nothing_with_appendix"
726731
get :render_template_in_top_directory, to: "test#render_template_in_top_directory"
@@ -785,6 +790,29 @@ def test_simple_show
785790
assert_equal "<html>Hello world!</html>", @response.body
786791
end
787792

793+
def test_controller_does_not_leak_instance_variables
794+
expected = [
795+
:@_assigns, # attr_internal on ActionView::Base
796+
:@_config, # attr_internal on ActionView::Base
797+
:@_controller, # attr_internal on ActionView::Helpers::ControllerHelper
798+
:@_default_form_builder, # attr_internal on ActionView::Helpers::FormHelper
799+
:@_ivars, # ActionController::Testing::Functional (only appears inside an ActionController::TestCase)
800+
:@_request, # attr_internal on ActionView::Helpers::ControllerHelper
801+
:@current_template, # instance variable on ActionView::Base
802+
:@lookup_context, # attr_reader on ActionView::Base
803+
:@output_buffer, # attr_accessor on ActionView::Base::Context
804+
:@variable_for_layout, # part of this test class
805+
:@view_flow, # attr_accessor on ActionView::Base::Context
806+
:@view_renderer, # attr_reader on ActionView::Base
807+
:@virtual_path, # instance variable on ActionView::Base
808+
].inspect
809+
810+
get :render_instance_variables
811+
812+
assert_response 200
813+
assert_equal expected, @response.body
814+
end
815+
788816
# :ported:
789817
def test_renders_default_template_for_missing_action
790818
get :'hyphen-ated'

0 commit comments

Comments
 (0)