VYPR
Moderate severityNVD Advisory· Published Feb 14, 2011· Updated Apr 29, 2026

CVE-2011-0447

CVE-2011-0447

Description

Ruby on Rails 2.1.x, 2.2.x, and 2.3.x before 2.3.11, and 3.x before 3.0.4, does not properly validate HTTP requests that contain an X-Requested-With header, which makes it easier for remote attackers to conduct cross-site request forgery (CSRF) attacks via forged (1) AJAX or (2) API requests that leverage "combinations of browser plugins and HTTP redirects," a related issue to CVE-2011-0696.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
actionpackRubyGems
>= 2.1.0, < 2.3.112.3.11
actionpackRubyGems
>= 3.0.0, < 3.0.43.0.4

Affected products

24
  • Rubyonrails/Rails24 versions
    cpe:2.3:a:rubyonrails:rails:2.1.0:*:*:*:*:*:*:*+ 23 more
    • cpe:2.3:a:rubyonrails:rails:2.1.0:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:2.1.1:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:2.1.2:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:2.2.0:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:2.2.1:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:2.2.2:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:2.3.10:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:2.3.2:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:2.3.3:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:2.3.4:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:2.3.9:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:3.0.0:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:3.0.0:beta:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:3.0.0:beta2:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:3.0.0:beta3:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:3.0.0:beta4:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:3.0.0:rc:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:3.0.0:rc2:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:3.0.1:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:3.0.1:pre:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:3.0.2:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:3.0.2:pre:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:3.0.3:*:*:*:*:*:*:*
    • cpe:2.3:a:rubyonrails:rails:3.0.4:rc1:*:*:*:*:*:*

Patches

2
7e86f9b4d2b7

Change the CSRF whitelisting to only apply to get requests

https://github.com/rails/railsMichael KoziarskiJan 17, 2011via ghsa
4 files changed · +117 130
  • actionpack/lib/action_controller/request_forgery_protection.rb+9 6 modified
    @@ -76,7 +76,11 @@ def protect_from_forgery(options = {})
         protected
           # The actual before_filter that is used.  Modify this to change how you handle unverified requests.
           def verify_authenticity_token
    -        verified_request? || raise(ActionController::InvalidAuthenticityToken)
    +        verified_request? || handle_unverified_request
    +      end
    +
    +      def handle_unverified_request
    +        reset_session
           end
           
           # Returns true or false if a request is verified.  Checks:
    @@ -85,11 +89,10 @@ def verify_authenticity_token
           # * is it a GET request?  Gets should be safe and idempotent
           # * Does the form_authenticity_token match the given token value from the params?
           def verified_request?
    -        !protect_against_forgery?     ||
    -          request.method == :get      ||
    -          request.xhr?                ||
    -          !verifiable_request_format? ||
    -          form_authenticity_token == form_authenticity_param
    +        !protect_against_forgery?                            ||
    +          request.get?                                       ||
    +          form_authenticity_token == form_authenticity_param ||
    +          form_authenticity_token == request.headers['X-CSRF-Token']
           end
     
           def form_authenticity_param
    
  • actionpack/lib/action_view/helpers/csrf_helper.rb+14 0 added
    @@ -0,0 +1,14 @@
    +module ActionView
    +  # = Action View CSRF Helper
    +  module Helpers
    +    module CsrfHelper
    +      # Returns a meta tag with the cross-site request forgery protection token
    +      # for forms to use. Place this in your head.
    +      def csrf_meta_tag
    +        if protect_against_forgery?
    +          %(<meta name="csrf-param" content="#{h(request_forgery_protection_token)}"/>\n<meta name="csrf-token" content="#{h(form_authenticity_token)}"/>).html_safe
    +        end
    +      end
    +    end
    +  end
    +end
    
  • actionpack/lib/action_view/helpers.rb+2 0 modified
    @@ -6,6 +6,7 @@ module Helpers #:nodoc:
         autoload :BenchmarkHelper, 'action_view/helpers/benchmark_helper'
         autoload :CacheHelper, 'action_view/helpers/cache_helper'
         autoload :CaptureHelper, 'action_view/helpers/capture_helper'
    +    autoload :CsrfHelper, 'action_view/helpers/csrf_helper'
         autoload :DateHelper, 'action_view/helpers/date_helper'
         autoload :DebugHelper, 'action_view/helpers/debug_helper'
         autoload :FormHelper, 'action_view/helpers/form_helper'
    @@ -38,6 +39,7 @@ module ClassMethods
         include BenchmarkHelper
         include CacheHelper
         include CaptureHelper
    +    include CsrfHelper
         include DateHelper
         include DebugHelper
         include FormHelper
    
  • actionpack/test/controller/request_forgery_protection_test.rb+92 124 modified
    @@ -23,6 +23,10 @@ def unsafe
         render :text => 'pwn'
       end
     
    +  def meta
    +    render :inline => "<%= csrf_meta_tag %>"
    +  end
    +
       def rescue_action(e) raise e end
     end
     
    @@ -32,6 +36,16 @@ class RequestForgeryProtectionController < ActionController::Base
       protect_from_forgery :only => :index
     end
     
    +class RequestForgeryProtectionControllerUsingOldBehaviour < ActionController::Base
    +  include RequestForgeryProtectionActions
    +  protect_from_forgery :only => %w(index meta)
    +
    +  def handle_unverified_request
    +    raise(ActionController::InvalidAuthenticityToken)
    +  end
    +end
    +
    +
     class FreeCookieController < RequestForgeryProtectionController
       self.allow_forgery_protection = false
       
    @@ -54,158 +68,92 @@ def form_authenticity_param
     # common test methods
     
     module RequestForgeryProtectionTests
    -  def teardown
    -    ActionController::Base.request_forgery_protection_token = nil
    -  end
    -  
    +  def setup
    +    @token      = "cf50faa3fe97702ca1ae"
     
    -  def test_should_render_form_with_token_tag
    -     get :index
    -     assert_select 'form>div>input[name=?][value=?]', 'authenticity_token', @token
    -   end
    -
    -   def test_should_render_button_to_with_token_tag
    -     get :show_button
    -     assert_select 'form>div>input[name=?][value=?]', 'authenticity_token', @token
    -   end
    -
    -   def test_should_render_remote_form_with_only_one_token_parameter
    -     get :remote_form
    -     assert_equal 1, @response.body.scan(@token).size
    -   end
    -
    -   def test_should_allow_get
    -     get :index
    -     assert_response :success
    -   end
    -
    -   def test_should_allow_post_without_token_on_unsafe_action
    -     post :unsafe
    -     assert_response :success
    -   end
    -
    -  def test_should_not_allow_html_post_without_token
    -    @request.env['CONTENT_TYPE'] = Mime::URL_ENCODED_FORM.to_s
    -    assert_raise(ActionController::InvalidAuthenticityToken) { post :index, :format => :html }
    +    ActiveSupport::SecureRandom.stubs(:base64).returns(@token)
    +    ActionController::Base.request_forgery_protection_token = :authenticity_token
       end
       
    -  def test_should_not_allow_html_put_without_token
    -    @request.env['CONTENT_TYPE'] = Mime::URL_ENCODED_FORM.to_s
    -    assert_raise(ActionController::InvalidAuthenticityToken) { put :index, :format => :html }
    -  end
       
    -  def test_should_not_allow_html_delete_without_token
    -    @request.env['CONTENT_TYPE'] = Mime::URL_ENCODED_FORM.to_s
    -    assert_raise(ActionController::InvalidAuthenticityToken) { delete :index, :format => :html }
    -  end
    -
    -  def test_should_allow_api_formatted_post_without_token
    -    assert_nothing_raised do
    -      post :index, :format => 'xml'
    +  def test_should_render_form_with_token_tag
    +    assert_not_blocked do
    +      get :index
         end
    +    assert_select 'form>div>input[name=?][value=?]', 'authenticity_token', @token
       end
     
    -  def test_should_not_allow_api_formatted_put_without_token
    -    assert_nothing_raised do
    -      put :index, :format => 'xml'
    +  def test_should_render_button_to_with_token_tag
    +    assert_not_blocked do
    +      get :show_button
         end
    +    assert_select 'form>div>input[name=?][value=?]', 'authenticity_token', @token
       end
     
    -  def test_should_allow_api_formatted_delete_without_token
    -    assert_nothing_raised do
    -      delete :index, :format => 'xml'
    -    end
    +  def test_should_allow_get
    +    assert_not_blocked { get :index }
       end
     
    -  def test_should_not_allow_api_formatted_post_sent_as_url_encoded_form_without_token
    -    assert_raise(ActionController::InvalidAuthenticityToken) do
    -      @request.env['CONTENT_TYPE'] = Mime::URL_ENCODED_FORM.to_s
    -      post :index, :format => 'xml'
    -    end
    +  def test_should_allow_post_without_token_on_unsafe_action
    +    assert_not_blocked { post :unsafe }
       end
     
    -  def test_should_not_allow_api_formatted_put_sent_as_url_encoded_form_without_token
    -    assert_raise(ActionController::InvalidAuthenticityToken) do
    -      @request.env['CONTENT_TYPE'] = Mime::URL_ENCODED_FORM.to_s
    -      put :index, :format => 'xml'
    -    end
    +  def test_should_not_allow_post_without_token
    +    assert_blocked { post :index }
       end
     
    -  def test_should_not_allow_api_formatted_delete_sent_as_url_encoded_form_without_token
    -    assert_raise(ActionController::InvalidAuthenticityToken) do
    -      @request.env['CONTENT_TYPE'] = Mime::URL_ENCODED_FORM.to_s
    -      delete :index, :format => 'xml'
    -    end
    +  def test_should_not_allow_post_without_token_irrespective_of_format
    +    assert_blocked { post :index, :format=>'xml' }
       end
     
    -  def test_should_not_allow_api_formatted_post_sent_as_multipart_form_without_token
    -    assert_raise(ActionController::InvalidAuthenticityToken) do
    -      @request.env['CONTENT_TYPE'] = Mime::MULTIPART_FORM.to_s
    -      post :index, :format => 'xml'
    -    end
    +  def test_should_not_allow_put_without_token
    +    assert_blocked { put :index }
       end
     
    -  def test_should_not_allow_api_formatted_put_sent_as_multipart_form_without_token
    -    assert_raise(ActionController::InvalidAuthenticityToken) do
    -      @request.env['CONTENT_TYPE'] = Mime::MULTIPART_FORM.to_s
    -      put :index, :format => 'xml'
    -    end
    +  def test_should_not_allow_delete_without_token
    +    assert_blocked { delete :index }
       end
     
    -  def test_should_not_allow_api_formatted_delete_sent_as_multipart_form_without_token
    -    assert_raise(ActionController::InvalidAuthenticityToken) do
    -      @request.env['CONTENT_TYPE'] = Mime::MULTIPART_FORM.to_s
    -      delete :index, :format => 'xml'
    -    end
    -  end
    -  
    -  def test_should_allow_xhr_post_without_token
    -    assert_nothing_raised { xhr :post, :index }
    -  end
    -  
    -  def test_should_allow_xhr_put_without_token
    -    assert_nothing_raised { xhr :put, :index }
    -  end
    -  
    -  def test_should_allow_xhr_delete_without_token
    -    assert_nothing_raised { xhr :delete, :index }
    +  def test_should_not_allow_xhr_post_without_token
    +    assert_blocked { xhr :post, :index }
       end
    -  
    -  def test_should_allow_xhr_post_with_encoded_form_content_type_without_token
    -    @request.env['CONTENT_TYPE'] = Mime::URL_ENCODED_FORM.to_s
    -    assert_nothing_raised { xhr :post, :index }
    -  end
    -  
    +
       def test_should_allow_post_with_token
    -    post :index, :authenticity_token => @token
    -    assert_response :success
    +    assert_not_blocked { post :index, :authenticity_token => @token }
       end
       
       def test_should_allow_put_with_token
    -    put :index, :authenticity_token => @token
    -    assert_response :success
    +    assert_not_blocked { put :index, :authenticity_token => @token }
       end
       
       def test_should_allow_delete_with_token
    -    delete :index, :authenticity_token => @token
    -    assert_response :success
    +    assert_not_blocked { delete :index, :authenticity_token => @token }
       end
       
    -  def test_should_allow_post_with_xml
    -    @request.env['CONTENT_TYPE'] = Mime::XML.to_s
    -    post :index, :format => 'xml'
    -    assert_response :success
    +  def test_should_allow_post_with_token_in_header
    +    @request.env['HTTP_X_CSRF_TOKEN'] = @token
    +    assert_not_blocked { post :index }
    +  end
    +
    +  def test_should_allow_delete_with_token_in_header
    +    @request.env['HTTP_X_CSRF_TOKEN'] = @token
    +    assert_not_blocked { delete :index }
       end
       
    -  def test_should_allow_put_with_xml
    -    @request.env['CONTENT_TYPE'] = Mime::XML.to_s
    -    put :index, :format => 'xml'
    +  def test_should_allow_put_with_token_in_header
    +    @request.env['HTTP_X_CSRF_TOKEN'] = @token
    +    assert_not_blocked { put :index }
    +  end
    +
    +  def assert_blocked
    +    session[:something_like_user_id] = 1
    +    yield
    +    assert_nil session[:something_like_user_id], "session values are still present"
         assert_response :success
       end
       
    -  def test_should_allow_delete_with_xml
    -    @request.env['CONTENT_TYPE'] = Mime::XML.to_s
    -    delete :index, :format => 'xml'
    +  def assert_not_blocked
    +    assert_nothing_raised { yield }
         assert_response :success
       end
     end
    @@ -214,15 +162,20 @@ def test_should_allow_delete_with_xml
     
     class RequestForgeryProtectionControllerTest < ActionController::TestCase
       include RequestForgeryProtectionTests
    -  def setup
    -    @controller = RequestForgeryProtectionController.new
    -    @request    = ActionController::TestRequest.new
    -    @request.format = :html
    -    @response   = ActionController::TestResponse.new
    -    @token      = "cf50faa3fe97702ca1ae"
     
    -    ActiveSupport::SecureRandom.stubs(:base64).returns(@token)
    -    ActionController::Base.request_forgery_protection_token = :authenticity_token
    +  test 'should emit a csrf-token meta tag' do
    +    ActiveSupport::SecureRandom.stubs(:base64).returns(@token + '<=?')
    +    get :meta
    +    assert_equal %(<meta name="csrf-param" content="authenticity_token"/>\n<meta name="csrf-token" content="cf50faa3fe97702ca1ae&lt;=?"/>), @response.body
    +  end
    +end
    +
    +class RequestForgeryProtectionControllerUsingOldBehaviourTest < ActionController::TestCase
    +  include RequestForgeryProtectionTests
    +  def assert_blocked
    +    assert_raises(ActionController::InvalidAuthenticityToken) do
    +      yield
    +    end
       end
     end
     
    @@ -251,15 +204,30 @@ def test_should_allow_all_methods_without_token
           assert_nothing_raised { send(method, :index)}
         end
       end
    +
    +  test 'should not emit a csrf-token meta tag' do
    +    get :meta
    +    assert_blank @response.body
    +  end
     end
     
    +
    +
    +
    +
     class CustomAuthenticityParamControllerTest < ActionController::TestCase
       def setup
    +    ActionController::Base.request_forgery_protection_token = :custom_token_name
    +    super
    +  end
    +
    +  def teardown
         ActionController::Base.request_forgery_protection_token = :authenticity_token
    +    super
       end
     
       def test_should_allow_custom_token
    -    post :index, :authenticity_token => 'foobar'
    +    post :index, :custom_token_name => 'foobar'
         assert_response :ok
       end
     end
    
66ce3843d32e

Change the CSRF whitelisting to only apply to get requests

https://github.com/rails/railsMichael KoziarskiJan 5, 2011via ghsa
3 files changed · +88 131
  • actionpack/lib/action_controller/metal/request_forgery_protection.rb+9 10 modified
    @@ -89,25 +89,24 @@ def protect_from_forgery(options = {})
         end
     
         protected
    -
    -      def protect_from_forgery(options = {})
    -        self.request_forgery_protection_token ||= :authenticity_token
    -        before_filter :verify_authenticity_token, options
    -      end
    -
           # The actual before_filter that is used.  Modify this to change how you handle unverified requests.
           def verify_authenticity_token
    -        verified_request? || raise(ActionController::InvalidAuthenticityToken)
    +        verified_request? || handle_unverified_request
    +      end
    +
    +      def handle_unverified_request
    +        reset_session
           end
     
           # Returns true or false if a request is verified.  Checks:
           #
    -      # * is the format restricted?  By default, only HTML requests are checked.
           # * is it a GET request?  Gets should be safe and idempotent
           # * Does the form_authenticity_token match the given token value from the params?
    +      # * Does the X-CSRF-Token header match the form_authenticity_token
           def verified_request?
    -        !protect_against_forgery? || request.forgery_whitelisted? ||
    -          form_authenticity_token == params[request_forgery_protection_token]
    +        !protect_against_forgery? || request.get? ||
    +          form_authenticity_token == params[request_forgery_protection_token] ||
    +          form_authenticity_token == request.headers['X-CSRF-Token']
           end
     
           # Sets the token value for the current session.
    
  • actionpack/lib/action_dispatch/http/request.rb+2 1 modified
    @@ -141,8 +141,9 @@ def fullpath
         end
     
         def forgery_whitelisted?
    -      get? || xhr? || content_mime_type.nil? || !content_mime_type.verify_request?
    +      get?
         end
    +    deprecate :forgery_whitelisted? => "it is just an alias for 'get?' now, update your code"
     
         def media_type
           content_mime_type.to_s
    
  • actionpack/test/controller/request_forgery_protection_test.rb+77 120 modified
    @@ -1,5 +1,4 @@
     require 'abstract_unit'
    -require 'digest/sha1'
     
     # common controller actions
     module RequestForgeryProtectionActions
    @@ -28,6 +27,16 @@ class RequestForgeryProtectionController < ActionController::Base
       protect_from_forgery :only => %w(index meta)
     end
     
    +class RequestForgeryProtectionControllerUsingOldBehaviour < ActionController::Base
    +  include RequestForgeryProtectionActions
    +  protect_from_forgery :only => %w(index meta)
    +
    +  def handle_unverified_request
    +    raise(ActionController::InvalidAuthenticityToken)
    +  end
    +end
    +
    +
     class FreeCookieController < RequestForgeryProtectionController
       self.allow_forgery_protection = false
     
    @@ -50,153 +59,92 @@ def form_authenticity_param
     # common test methods
     
     module RequestForgeryProtectionTests
    -  def teardown
    -    ActionController::Base.request_forgery_protection_token = nil
    -  end
    -
    -
    -  def test_should_render_form_with_token_tag
    -     get :index
    -     assert_select 'form>div>input[name=?][value=?]', 'authenticity_token', @token
    -   end
    -
    -   def test_should_render_button_to_with_token_tag
    -     get :show_button
    -     assert_select 'form>div>input[name=?][value=?]', 'authenticity_token', @token
    -   end
    -
    -   def test_should_allow_get
    -     get :index
    -     assert_response :success
    -   end
    -
    -   def test_should_allow_post_without_token_on_unsafe_action
    -     post :unsafe
    -     assert_response :success
    -   end
    -
    -  def test_should_not_allow_html_post_without_token
    -    @request.env['CONTENT_TYPE'] = Mime::URL_ENCODED_FORM.to_s
    -    assert_raise(ActionController::InvalidAuthenticityToken) { post :index, :format => :html }
    -  end
    -
    -  def test_should_not_allow_html_put_without_token
    -    @request.env['CONTENT_TYPE'] = Mime::URL_ENCODED_FORM.to_s
    -    assert_raise(ActionController::InvalidAuthenticityToken) { put :index, :format => :html }
    -  end
    -
    -  def test_should_not_allow_html_delete_without_token
    -    @request.env['CONTENT_TYPE'] = Mime::URL_ENCODED_FORM.to_s
    -    assert_raise(ActionController::InvalidAuthenticityToken) { delete :index, :format => :html }
    -  end
    +  def setup
    +    @token      = "cf50faa3fe97702ca1ae"
     
    -  def test_should_allow_api_formatted_post_without_token
    -    assert_nothing_raised do
    -      post :index, :format => 'xml'
    -    end
    +    ActiveSupport::SecureRandom.stubs(:base64).returns(@token)
    +    ActionController::Base.request_forgery_protection_token = :authenticity_token
       end
     
    -  def test_should_not_allow_api_formatted_put_without_token
    -    assert_nothing_raised do
    -      put :index, :format => 'xml'
    -    end
    -  end
     
    -  def test_should_allow_api_formatted_delete_without_token
    -    assert_nothing_raised do
    -      delete :index, :format => 'xml'
    +  def test_should_render_form_with_token_tag
    +    assert_not_blocked do
    +      get :index
         end
    +    assert_select 'form>div>input[name=?][value=?]', 'authenticity_token', @token
       end
     
    -  def test_should_not_allow_api_formatted_post_sent_as_url_encoded_form_without_token
    -    assert_raise(ActionController::InvalidAuthenticityToken) do
    -      @request.env['CONTENT_TYPE'] = Mime::URL_ENCODED_FORM.to_s
    -      post :index, :format => 'xml'
    +  def test_should_render_button_to_with_token_tag
    +    assert_not_blocked do
    +      get :show_button
         end
    +    assert_select 'form>div>input[name=?][value=?]', 'authenticity_token', @token
       end
     
    -  def test_should_not_allow_api_formatted_put_sent_as_url_encoded_form_without_token
    -    assert_raise(ActionController::InvalidAuthenticityToken) do
    -      @request.env['CONTENT_TYPE'] = Mime::URL_ENCODED_FORM.to_s
    -      put :index, :format => 'xml'
    -    end
    +  def test_should_allow_get
    +    assert_not_blocked { get :index }
       end
     
    -  def test_should_not_allow_api_formatted_delete_sent_as_url_encoded_form_without_token
    -    assert_raise(ActionController::InvalidAuthenticityToken) do
    -      @request.env['CONTENT_TYPE'] = Mime::URL_ENCODED_FORM.to_s
    -      delete :index, :format => 'xml'
    -    end
    +  def test_should_allow_post_without_token_on_unsafe_action
    +    assert_not_blocked { post :unsafe }
       end
     
    -  def test_should_not_allow_api_formatted_post_sent_as_multipart_form_without_token
    -    assert_raise(ActionController::InvalidAuthenticityToken) do
    -      @request.env['CONTENT_TYPE'] = Mime::MULTIPART_FORM.to_s
    -      post :index, :format => 'xml'
    -    end
    +  def test_should_not_allow_post_without_token
    +    assert_blocked { post :index }
       end
     
    -  def test_should_not_allow_api_formatted_put_sent_as_multipart_form_without_token
    -    assert_raise(ActionController::InvalidAuthenticityToken) do
    -      @request.env['CONTENT_TYPE'] = Mime::MULTIPART_FORM.to_s
    -      put :index, :format => 'xml'
    -    end
    +  def test_should_not_allow_post_without_token_irrespective_of_format
    +    assert_blocked { post :index, :format=>'xml' }
       end
     
    -  def test_should_not_allow_api_formatted_delete_sent_as_multipart_form_without_token
    -    assert_raise(ActionController::InvalidAuthenticityToken) do
    -      @request.env['CONTENT_TYPE'] = Mime::MULTIPART_FORM.to_s
    -      delete :index, :format => 'xml'
    -    end
    +  def test_should_not_allow_put_without_token
    +    assert_blocked { put :index }
       end
     
    -  def test_should_allow_xhr_post_without_token
    -    assert_nothing_raised { xhr :post, :index }
    +  def test_should_not_allow_delete_without_token
    +    assert_blocked { delete :index }
       end
     
    -  def test_should_allow_xhr_put_without_token
    -    assert_nothing_raised { xhr :put, :index }
    +  def test_should_not_allow_xhr_post_without_token
    +    assert_blocked { xhr :post, :index }
       end
     
    -  def test_should_allow_xhr_delete_without_token
    -    assert_nothing_raised { xhr :delete, :index }
    +  def test_should_allow_post_with_token
    +    assert_not_blocked { post :index, :authenticity_token => @token }
       end
     
    -  def test_should_allow_xhr_post_with_encoded_form_content_type_without_token
    -    @request.env['CONTENT_TYPE'] = Mime::URL_ENCODED_FORM.to_s
    -    assert_nothing_raised { xhr :post, :index }
    +  def test_should_allow_put_with_token
    +    assert_not_blocked { put :index, :authenticity_token => @token }
       end
     
    -  def test_should_allow_post_with_token
    -    post :index, :authenticity_token => @token
    -    assert_response :success
    +  def test_should_allow_delete_with_token
    +    assert_not_blocked { delete :index, :authenticity_token => @token }
       end
     
    -  def test_should_allow_put_with_token
    -    put :index, :authenticity_token => @token
    -    assert_response :success
    +  def test_should_allow_post_with_token_in_header
    +    @request.env['HTTP_X_CSRF_TOKEN'] = @token
    +    assert_not_blocked { post :index }
       end
     
    -  def test_should_allow_delete_with_token
    -    delete :index, :authenticity_token => @token
    -    assert_response :success
    +  def test_should_allow_delete_with_token_in_header
    +    @request.env['HTTP_X_CSRF_TOKEN'] = @token
    +    assert_not_blocked { delete :index }
       end
     
    -  def test_should_allow_post_with_xml
    -    @request.env['CONTENT_TYPE'] = Mime::XML.to_s
    -    post :index, :format => 'xml'
    -    assert_response :success
    +  def test_should_allow_put_with_token_in_header
    +    @request.env['HTTP_X_CSRF_TOKEN'] = @token
    +    assert_not_blocked { put :index }
       end
     
    -  def test_should_allow_put_with_xml
    -    @request.env['CONTENT_TYPE'] = Mime::XML.to_s
    -    put :index, :format => 'xml'
    +  def assert_blocked
    +    session[:something_like_user_id] = 1
    +    yield
    +    assert_nil session[:something_like_user_id], "session values are still present"
         assert_response :success
       end
     
    -  def test_should_allow_delete_with_xml
    -    @request.env['CONTENT_TYPE'] = Mime::XML.to_s
    -    delete :index, :format => 'xml'
    +  def assert_not_blocked
    +    assert_nothing_raised { yield }
         assert_response :success
       end
     end
    @@ -205,16 +153,6 @@ def test_should_allow_delete_with_xml
     
     class RequestForgeryProtectionControllerTest < ActionController::TestCase
       include RequestForgeryProtectionTests
    -  def setup
    -    @controller = RequestForgeryProtectionController.new
    -    @request    = ActionController::TestRequest.new
    -    @request.format = :html
    -    @response   = ActionController::TestResponse.new
    -    @token      = "cf50faa3fe97702ca1ae"
    -
    -    ActiveSupport::SecureRandom.stubs(:base64).returns(@token)
    -    ActionController::Base.request_forgery_protection_token = :authenticity_token
    -  end
     
       test 'should emit a csrf-token meta tag' do
         ActiveSupport::SecureRandom.stubs(:base64).returns(@token + '<=?')
    @@ -223,6 +161,15 @@ def setup
       end
     end
     
    +class RequestForgeryProtectionControllerUsingOldBehaviourTest < ActionController::TestCase
    +  include RequestForgeryProtectionTests
    +  def assert_blocked
    +    assert_raises(ActionController::InvalidAuthenticityToken) do
    +      yield
    +    end
    +  end
    +end
    +
     class FreeCookieControllerTest < ActionController::TestCase
       def setup
         @controller = FreeCookieController.new
    @@ -255,13 +202,23 @@ def test_should_allow_all_methods_without_token
       end
     end
     
    +
    +
    +
    +
     class CustomAuthenticityParamControllerTest < ActionController::TestCase
       def setup
    +    ActionController::Base.request_forgery_protection_token = :custom_token_name
    +    super
    +  end
    +
    +  def teardown
         ActionController::Base.request_forgery_protection_token = :authenticity_token
    +    super
       end
     
       def test_should_allow_custom_token
    -    post :index, :authenticity_token => 'foobar'
    +    post :index, :custom_token_name => 'foobar'
         assert_response :ok
       end
     end
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

19

News mentions

0

No linked articles in our index yet.