Yejun Su

January 14, 2023

Rails loads configuration unexpectedly caused by gems

This article was written when one of our Rails applications was upgraded to Rails 5.2.

After upgrading our application to Rails 5.2, InvalidAuthenticityToken errors are found in our public APIs. The error is caused by CSRF protection is enabled by default since Rails 5.2 while it is not required in public APIs. I updated the config to disable the default behavior, but it doesn't take effect.
# config/initializers/new_framework_defaults_5_2.rb
Rails.application.config.action_controller.default_protect_from_forgery = false

The problem

According to the source code, the config is used to toggle CSRF protection after ActionController::Base is loaded:
initializer "action_controller.request_forgery_protection" do |app|
  ActiveSupport.on_load(:action_controller_base) do
    puts "default_protect_from_forgery: #{app.config.action_controller.default_protect_from_forgery}" # Add this line to print the config value
    if app.config.action_controller.default_protect_from_forgery
      protect_from_forgery with: :exception
    end
  end
end

I use this gist to debug how configurations are loaded:
before_configuration
application.rb loaded
before_initialize
default_protect_from_forgery is true, expected: false
config/initializers loaded
ActiveSupport.on_load(:before_initialize) runs at the end of before_initialize
after_initialize
default_protect_from_forgery is false, expected: false
ActiveSupport.on_load(:after_initialize) runs at the end of after_initialize
The red-colored line shows the default_protect_from_forgery is true while it is expected to be false. So the problem is ActionController::Base is loaded before loading config/initializers.

Investigation

I commented all gems except the rails gem, then uncommented them one by one and debug configuration loading with rails c to see the prints like above, finally found it is caused by the wechat gem:
https://github.com/Eric-Guo/wechat/blob/v0.12.2/lib/wechat.rb#L10
https://github.com/Eric-Guo/wechat/blob/v0.12.2/lib/action_controller/wechat_responder.rb#L68

Solution

The problem can be fixed if:
I created a repo for showing the problem, you can see two commits:

- Yejun

About Yejun Su

Software engineer @eduvo. I write about software development, work and life.