diff --git a/actioncable/CHANGELOG.md b/actioncable/CHANGELOG.md index 137c88d91be..d70d32ce078 100644 --- a/actioncable/CHANGELOG.md +++ b/actioncable/CHANGELOG.md @@ -1,3 +1,10 @@ +* Permit same-origin connections by default. + + New option `config.action_cable.allow_same_origin_as_host = false` + to disable. + + *Dávid Halász*, *Matthew Draper* + * Prevent race where the client could receive and act upon a subscription confirmation before the channel's `subscribed` method completed. diff --git a/actioncable/README.md b/actioncable/README.md index 30b86edd2ed..8ad9aeb1f1d 100644 --- a/actioncable/README.md +++ b/actioncable/README.md @@ -326,7 +326,10 @@ Rails.application.paths.add "config/cable", with: "somewhere/else/cable.yml" ### Allowed Request Origins -Action Cable will only accept requests from specified origins, which are passed to the server config as an array. The origins can be instances of strings or regular expressions, against which a check for match will be performed. +Action Cable will only accept requests from specific origins. + +By default, only an origin matching the cable server itself will be permitted. +Additional origins can be specified using strings or regular expressions, provided in an array. ```ruby Rails.application.config.action_cable.allowed_request_origins = ['http://rubyonrails.com', /http:\/\/ruby.*/] @@ -334,15 +337,17 @@ Rails.application.config.action_cable.allowed_request_origins = ['http://rubyonr When running in the development environment, this defaults to "http://localhost:3000". -To disable and allow requests from any origin: +To disable protection and allow requests from any origin: ```ruby Rails.application.config.action_cable.disable_request_forgery_protection = true ``` -It is also possible to allow origins that are starting with the actual HTTP HOST header: +To disable automatic access for same-origin requests, and strictly allow +only the configured origins: + ```ruby -Rails.application.config.action_cable.allow_same_origin_as_host = true +Rails.application.config.action_cable.allow_same_origin_as_host = false ``` ### Consumer Configuration diff --git a/actioncable/lib/action_cable/connection/base.rb b/actioncable/lib/action_cable/connection/base.rb index 25966357011..dfee123ea2d 100644 --- a/actioncable/lib/action_cable/connection/base.rb +++ b/actioncable/lib/action_cable/connection/base.rb @@ -196,9 +196,9 @@ module ActionCable return true if server.config.disable_request_forgery_protection proto = Rack::Request.new(env).ssl? ? "https" : "http" - if Array(server.config.allowed_request_origins).any? { |allowed_origin| allowed_origin === env["HTTP_ORIGIN"] } + if server.config.allow_same_origin_as_host && env["HTTP_ORIGIN"] == "#{proto}://#{env['HTTP_HOST']}" true - elsif server.config.allow_same_origin_as_host && env["HTTP_ORIGIN"] == "#{proto}://#{env['HTTP_HOST']}" + elsif Array(server.config.allowed_request_origins).any? { |allowed_origin| allowed_origin === env["HTTP_ORIGIN"] } true else logger.error("Request origin not allowed: #{env['HTTP_ORIGIN']}") diff --git a/actioncable/lib/action_cable/server/configuration.rb b/actioncable/lib/action_cable/server/configuration.rb index aa8d10b3d4d..17e0dee064e 100644 --- a/actioncable/lib/action_cable/server/configuration.rb +++ b/actioncable/lib/action_cable/server/configuration.rb @@ -15,7 +15,7 @@ module ActionCable @worker_pool_size = 4 @disable_request_forgery_protection = false - @allow_same_origin_as_host = false + @allow_same_origin_as_host = true end # Returns constant of subscription adapter specified in config/cable.yml. diff --git a/actioncable/test/connection/cross_site_forgery_test.rb b/actioncable/test/connection/cross_site_forgery_test.rb index 6cabff5440f..37bedfd7346 100644 --- a/actioncable/test/connection/cross_site_forgery_test.rb +++ b/actioncable/test/connection/cross_site_forgery_test.rb @@ -13,12 +13,13 @@ class ActionCable::Connection::CrossSiteForgeryTest < ActionCable::TestCase setup do @server = TestServer.new @server.config.allowed_request_origins = %w( http://rubyonrails.com ) + @server.config.allow_same_origin_as_host = false end teardown do @server.config.disable_request_forgery_protection = false @server.config.allowed_request_origins = [] - @server.config.allow_same_origin_as_host = false + @server.config.allow_same_origin_as_host = true end test "disable forgery protection" do