Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Changed request forgery protection to only worry about HTML-formatted…

… content requests.

Signed-off-by: Michael Koziarski <michael@koziarski.com>
  • Loading branch information...
commit fbbcd6f29aeccc938b97b5c01717365f8b67912c 1 parent 02df503
Jeff Cohen JeffCohen authored NZKoz committed
4 actionpack/lib/action_controller/mime_type.rb
View
@@ -19,7 +19,7 @@ module Mime
# end
# end
class Type
- @@html_types = Set.new [:html, :all]
+ @@html_types = Set.new [:html, :url_encoded_form, :multipart_form, :all]
@@unverifiable_types = Set.new [:text, :json, :csv, :xml, :rss, :atom, :yaml]
cattr_reader :html_types, :unverifiable_types
@@ -167,7 +167,7 @@ def ==(mime_type)
# Returns true if Action Pack should check requests using this Mime Type for possible request forgery. See
# ActionController::RequestForgerProtection.
def verify_request?
- !@@unverifiable_types.include?(to_sym)
+ html?
end
def html?
2  actionpack/lib/action_controller/request_forgery_protection.rb
View
@@ -99,7 +99,7 @@ def verified_request?
end
def verifiable_request_format?
- request.content_type.nil? || request.content_type.verify_request?
+ !request.content_type.nil? && request.content_type.verify_request?
end
# Sets the token value for the current session. Pass a <tt>:secret</tt> option
1  actionpack/lib/action_controller/test_process.rb
View
@@ -395,6 +395,7 @@ def process(action, parameters = nil, session = nil, flash = nil)
@html_document = nil
@request.env['REQUEST_METHOD'] ||= "GET"
+
@request.action = action.to_s
parameters ||= {}
118 actionpack/test/controller/request_forgery_protection_test.rb
View
@@ -77,57 +77,61 @@ 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
+ 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_raises(ActionController::InvalidAuthenticityToken) { post :index, :format => :html }
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
+ def test_should_not_allow_html_put_without_token
+ @request.env['CONTENT_TYPE'] = Mime::URL_ENCODED_FORM.to_s
+ assert_raises(ActionController::InvalidAuthenticityToken) { put :index, :format => :html }
end
- def test_should_allow_post_without_token_on_unsafe_action
- post :unsafe
- assert_response :success
+ def test_should_not_allow_html_delete_without_token
+ @request.env['CONTENT_TYPE'] = Mime::URL_ENCODED_FORM.to_s
+ assert_raises(ActionController::InvalidAuthenticityToken) { delete :index, :format => :html }
end
- def test_should_not_allow_post_without_token
- assert_raises(ActionController::InvalidAuthenticityToken) { post :index }
- end
-
- def test_should_not_allow_put_without_token
- assert_raises(ActionController::InvalidAuthenticityToken) { put :index }
- end
-
- def test_should_not_allow_delete_without_token
- assert_raises(ActionController::InvalidAuthenticityToken) { delete :index }
- end
-
- def test_should_not_allow_api_formatted_post_without_token
- assert_raises(ActionController::InvalidAuthenticityToken) do
+ def test_should_allow_api_formatted_post_without_token
+ assert_nothing_raised do
post :index, :format => 'xml'
end
end
def test_should_not_allow_api_formatted_put_without_token
- assert_raises(ActionController::InvalidAuthenticityToken) do
+ assert_nothing_raised do
put :index, :format => 'xml'
end
end
- def test_should_not_allow_api_formatted_delete_without_token
- assert_raises(ActionController::InvalidAuthenticityToken) do
+ def test_should_allow_api_formatted_delete_without_token
+ assert_nothing_raised do
delete :index, :format => 'xml'
end
end
@@ -174,16 +178,20 @@ def test_should_not_allow_api_formatted_delete_sent_as_multipart_form_without_to
end
end
- def test_should_not_allow_xhr_post_without_token
- assert_raises(ActionController::InvalidAuthenticityToken) { xhr :post, :index }
+ def test_should_allow_xhr_post_without_token
+ assert_nothing_raised { xhr :post, :index }
+ end
+ def test_should_not_allow_xhr_post_with_html_without_token
+ @request.env['CONTENT_TYPE'] = Mime::URL_ENCODED_FORM.to_s
+ assert_raise(ActionController::InvalidAuthenticityToken) { xhr :post, :index }
end
- def test_should_not_allow_xhr_put_without_token
- assert_raises(ActionController::InvalidAuthenticityToken) { xhr :put, :index }
+ def test_should_allow_xhr_put_without_token
+ assert_nothing_raised { xhr :put, :index }
end
- def test_should_not_allow_xhr_delete_without_token
- assert_raises(ActionController::InvalidAuthenticityToken) { xhr :delete, :index }
+ def test_should_allow_xhr_delete_without_token
+ assert_nothing_raised { xhr :delete, :index }
end
def test_should_allow_post_with_token
@@ -227,6 +235,7 @@ class RequestForgeryProtectionControllerTest < Test::Unit::TestCase
def setup
@controller = RequestForgeryProtectionController.new
@request = ActionController::TestRequest.new
+ @request.format = :html
@response = ActionController::TestResponse.new
class << @request.session
def session_id() '123' end
@@ -248,11 +257,11 @@ def session_id() '123' end
ActionController::Base.request_forgery_protection_token = :authenticity_token
end
- def test_should_raise_error_without_secret
- assert_raises ActionController::InvalidAuthenticityToken do
- get :index
- end
- end
+ # def test_should_raise_error_without_secret
+ # assert_raises ActionController::InvalidAuthenticityToken do
+ # get :index
+ # end
+ # end
end
class CsrfCookieMonsterControllerTest < Test::Unit::TestCase
@@ -304,10 +313,15 @@ def setup
@token = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new('SHA1'), 'abc', '123')
end
- def test_should_raise_correct_exception
- @request.session = {} # session(:off) doesn't appear to work with controller tests
- assert_raises(ActionController::InvalidAuthenticityToken) do
- post :index, :authenticity_token => @token
- end
- end
+ # TODO: Rewrite this test.
+ # This test was passing but for the wrong reason.
+ # Sessions aren't really being turned off, so an exception was raised
+ # because sessions weren't on - not because the token didn't match.
+ #
+ # def test_should_raise_correct_exception
+ # @request.session = {} # session(:off) doesn't appear to work with controller tests
+ # assert_raises(ActionController::InvalidAuthenticityToken) do
+ # post :index, :authenticity_token => @token, :format => :html
+ # end
+ # end
end

3 comments on commit fbbcd6f

Jason Roelofs

So…. What does this mean, exactly?

Brian Johnson

I don’t understand this. I have ajax calls that return json, aren’t they also susceptible to request forgery?

Michael Koziarski
Owner

it’s the request content type, not the response content type. i.e. what’s in the client’s Content-Type header.

This is never anything other than the browser_generated_types (see later commit).

Please sign in to comment.
Something went wrong with that request. Please try again.