Skip to content

Default protect from forgery#29742

Merged
rafaelfranca merged 2 commits into
rails:masterfrom
lugray:default_protect_from_forgery
Jul 10, 2017
Merged

Default protect from forgery#29742
rafaelfranca merged 2 commits into
rails:masterfrom
lugray:default_protect_from_forgery

Conversation

@lugray

@lugray lugray commented Jul 10, 2017

Copy link
Copy Markdown

Summary

Fixes #29193.

Protect from forgery by default: Rather than protecting from forgery in the generated ApplicationController, add it to ActionController::Base by config. This configuration defaults to false to support older versions which have removed it from their ApplicationController, but is set to true for Rails 5.2.

Also adds ActionController::Base.skip_forgery_protection as a wrapper to skip_before_action :verify_authenticity_token for disabling forgery protection.

@lugray lugray force-pushed the default_protect_from_forgery branch from 591df00 to 3aeaf53 Compare July 10, 2017 16:41
@lugray

lugray commented Jul 10, 2017

Copy link
Copy Markdown
Author

r? @rafaelfranca

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is also going to run for ActionController::Api, so it is better to use on_load(:action_controller_base here. That way we can do:

ActiveSupport.on_load(:action_controller_base) do
  if app.config.action_controller.default_protect_from_forgery
    protect_from_forgery with: :exception
  end
end

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to add this config to the configurations.md guide.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@lugray lugray force-pushed the default_protect_from_forgery branch from 3aeaf53 to 4bb3085 Compare July 10, 2017 18:08

@Edouard-chin Edouard-chin Jul 10, 2017

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small nitpicks, might use plus sign +skip_before_action+ for rdoc

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@lugray lugray force-pushed the default_protect_from_forgery branch from 4bb3085 to 393b333 Compare July 10, 2017 19:16

@rafaelfranca rafaelfranca left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Last thing. Could you add a CHANGELOG entry?

@lugray lugray force-pushed the default_protect_from_forgery branch from 393b333 to 5d72432 Compare July 10, 2017 19:25

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't necessary, since referencing ActionController::Base on the next line will run the lazy load hooks. It's only needed when testing ActionController::Parameters options, as loading that class won't trigger the hooks.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The behaviour here doesn't depend on the environment, so I'd ✂️ "on production" from the test name.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The rest of the tests in this file set this as "development" when the behaviour doesn't depend on the particular environment; we should probably do the same here for consistency.

Comment thread guides/source/configuring.md Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ActionController:Base -> ActionController::Base (with backticks 😊)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line needs a full stop at the end.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there should be a colon here:

This is a wrapper for:

@lugray lugray force-pushed the default_protect_from_forgery branch 2 times, most recently from e9b8b74 to 58af2b8 Compare July 10, 2017 19:50
@lugray

lugray commented Jul 10, 2017

Copy link
Copy Markdown
Author

Thanks @eugeneius, updated as per your review.

@eugeneius

Copy link
Copy Markdown
Member

This looks great! 👏

My only remaining question is whether there should be an entry in new_framework_defaults_5_2.rb for this, so that upgraded apps can opt-in to the new behaviour if they want it. My understanding of that file is that it should mirror the options from Rails::Application::Configuration#load_defaults.

Lisa Ugray added 2 commits July 10, 2017 16:23
Rather than protecting from forgery in the generated
ApplicationController, add it to ActionController::Base by config. This
configuration defaults to false to support older versions which have
removed it from their ApplicationController, but is set to true for
Rails 5.2.
Since we now default to `protect_from_forgery with: :exception`,
provide a wrapper to `skip_before_action :verify_authenticity_token`
for disabling forgery protection.
@lugray lugray force-pushed the default_protect_from_forgery branch from 58af2b8 to 73b944e Compare July 10, 2017 20:24
@lugray

lugray commented Jul 10, 2017

Copy link
Copy Markdown
Author

@eugeneius That makes sense. I added to new_framework_defaults_5_2.rb.tt

@rafaelfranca rafaelfranca merged commit 48cb8b3 into rails:master Jul 10, 2017
@lugray lugray deleted the default_protect_from_forgery branch July 10, 2017 21:27

# Add default protection from forgery to ActionController::Base instead of in
# ApplicationController.
# Rails.applocation.config.action_controller.default_protect_from_forgery = true

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a typo applocation

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I'll get a fix up.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, it already got fixed in e01b240.

@wnm

wnm commented Jan 24, 2018

Copy link
Copy Markdown

This configuration defaults to false to support older versions which have removed it from their ApplicationController, but is set to true for Rails 5.2.

@lugray don't older versions have it in ApplicationController, and the new default is there to move it to ActionController::Base so we can remove it from ApplicationController?

@lugray

lugray commented Jan 24, 2018

Copy link
Copy Markdown
Author

@wnm By default, older versions do have it in ApplicationController. The point I'm making is that the way to turn it off in older versions would have been to remove the line from the generated ApplicationController. If someone has actively removed it because they don't want it, upgrading should not change the behavior. But new applications will get the 5.2 defaults, which set it to true. If you're upgrading an older version of rails, and you want to remove it from ApplicationController, you'll need to change the configuration you use, since you won't have the 5.2 defaults.

@wnm

wnm commented Jan 24, 2018

Copy link
Copy Markdown

@lugray ah I see... totally makes sense. thanks for the quick response!!

@octavpo

octavpo commented Apr 24, 2018

Copy link
Copy Markdown

I think it would be better if the default_protect_from_forgery config could take the :with parameter as a value.

There's also an inconsistency in approach that if you use default_protect_from_forgery = true in config it defaults to :exception, while if you use protect_from_forgery with no parameters in the controller it defaults to :null_session.

@collimarco

Copy link
Copy Markdown
Contributor

There's also an inconsistency in approach that if you use default_protect_from_forgery = true in config it defaults to :exception, while if you use protect_from_forgery with no parameters in the controller it defaults to :null_session.

I totally agree! It is not clear from the docs that the default behavior is :exception.

ceritium added a commit to ceritium/featurer_web that referenced this pull request Jul 5, 2018
Rails 5.1 has the CSRF protection disabled by default but rails 5.2 enable it
again. rails/rails#29742

- Remove the fancy ajax delete.
- Use jquery_ujs for the delete action (it must be included by the host app at the moment).
- Add `csrf_meta_tags` on the layout.
jkeck added a commit to sul-dlss/vatican_exhibits that referenced this pull request Jul 21, 2018
Rails 5.2 added this behavior in rails/rails#29742 however it is false by default for backwards compatibility.
jkeck added a commit to sul-dlss/vatican_exhibits that referenced this pull request Jul 21, 2018
Rails 5.2 added this behavior in rails/rails#29742
camillevilla pushed a commit to sul-dlss/vatican_exhibits that referenced this pull request Jul 23, 2018
@swrobel

swrobel commented Aug 22, 2018

Copy link
Copy Markdown
Contributor

@lugray can you explain this?

There's also an inconsistency in approach that if you use default_protect_from_forgery = true in config it defaults to :exception, while if you use protect_from_forgery with no parameters in the controller it defaults to :null_session.

@rafaelfranca

Copy link
Copy Markdown
Member

Yes, we change the default to be :exception because :null_session was a bad default.

@rafaelfranca

Copy link
Copy Markdown
Member

It was the case already before this patch. https://github.com/rails/rails/pull/29742/files#diff-8380e0e11d4efeb2b0b142ae9e4cf512L3 Even that the default of the method is null_session, rails already generated the application using exception. That was the new default for applications not for the method.

@swrobel

swrobel commented Aug 22, 2018

Copy link
Copy Markdown
Contributor

@rafaelfranca I understand what you're saying, but for the 99.9% of Rails users who don't dig into the source code at this level, they're going to look at the docs for protect_from_forgery and see that null_session is the default and not understand why their 5.2 app is using exception. I don't see this anywhere in the 5.2 release notes, and while it's mentioned in the security guide I still think this creates a huge opportunity for confusion.

Would you at least be open to changing the default for protect_from_forgery to exception in 6.0 so it's consistent?

@rafaelfranca

Copy link
Copy Markdown
Member

I think it is worth considering it, but it will be a really annoying experience to most of the users given they will have to be explicit about the default to remove the deprecation warning. But I guess it will avoid confusion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants