Skip to content

Commit dae4044

Browse files
committedOct 11, 2016
Permit same-origin connections by default
WebSocket always defers the decision to the server, because it didn't have to deal with legacy compatibility... but the same-origin policy is still a reasonable default. Origin checks do not protect against a directly connecting attacker -- they can lie about their host, but can also lie about their origin. Origin checks protect against a connection from 3rd-party controlled script in a context where a victim browser's cookies will be passed along. And if an attacker has breached that protection, they've already compromised the HTTP session, so treating the WebSocket connection in the same way seems reasonable. In case this logic proves incorrect (or anyone just wants to be more paranoid), we retain a config option to disable it.
1 parent f8c53ef commit dae4044

File tree

5 files changed

+21
-8
lines changed

5 files changed

+21
-8
lines changed
 

‎actioncable/CHANGELOG.md

+7
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
* Permit same-origin connections by default.
2+
3+
New option `config.action_cable.allow_same_origin_as_host = false`
4+
to disable.
5+
6+
*Dávid Halász*, *Matthew Draper*
7+
18
* Prevent race where the client could receive and act upon a
29
subscription confirmation before the channel's `subscribed` method
310
completed.

‎actioncable/README.md

+9-4
Original file line numberDiff line numberDiff line change
@@ -326,23 +326,28 @@ Rails.application.paths.add "config/cable", with: "somewhere/else/cable.yml"
326326
327327
### Allowed Request Origins
328328
329-
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.
329+
Action Cable will only accept requests from specific origins.
330+
331+
By default, only an origin matching the cable server itself will be permitted.
332+
Additional origins can be specified using strings or regular expressions, provided in an array.
330333
331334
```ruby
332335
Rails.application.config.action_cable.allowed_request_origins = ['http://rubyonrails.com', /http:\/\/ruby.*/]
333336
```
334337

335338
When running in the development environment, this defaults to "http://localhost:3000".
336339

337-
To disable and allow requests from any origin:
340+
To disable protection and allow requests from any origin:
338341

339342
```ruby
340343
Rails.application.config.action_cable.disable_request_forgery_protection = true
341344
```
342345

343-
It is also possible to allow origins that are starting with the actual HTTP HOST header:
346+
To disable automatic access for same-origin requests, and strictly allow
347+
only the configured origins:
348+
344349
```ruby
345-
Rails.application.config.action_cable.allow_same_origin_as_host = true
350+
Rails.application.config.action_cable.allow_same_origin_as_host = false
346351
```
347352

348353
### Consumer Configuration

‎actioncable/lib/action_cable/connection/base.rb

+2-2
Original file line numberDiff line numberDiff line change
@@ -196,9 +196,9 @@ def allow_request_origin?
196196
return true if server.config.disable_request_forgery_protection
197197

198198
proto = Rack::Request.new(env).ssl? ? "https" : "http"
199-
if Array(server.config.allowed_request_origins).any? { |allowed_origin| allowed_origin === env["HTTP_ORIGIN"] }
199+
if server.config.allow_same_origin_as_host && env["HTTP_ORIGIN"] == "#{proto}://#{env['HTTP_HOST']}"
200200
true
201-
elsif server.config.allow_same_origin_as_host && env["HTTP_ORIGIN"] == "#{proto}://#{env['HTTP_HOST']}"
201+
elsif Array(server.config.allowed_request_origins).any? { |allowed_origin| allowed_origin === env["HTTP_ORIGIN"] }
202202
true
203203
else
204204
logger.error("Request origin not allowed: #{env['HTTP_ORIGIN']}")

‎actioncable/lib/action_cable/server/configuration.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ def initialize
1515
@worker_pool_size = 4
1616

1717
@disable_request_forgery_protection = false
18-
@allow_same_origin_as_host = false
18+
@allow_same_origin_as_host = true
1919
end
2020

2121
# Returns constant of subscription adapter specified in config/cable.yml.

‎actioncable/test/connection/cross_site_forgery_test.rb

+2-1
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,13 @@ def send_async(method, *args)
1313
setup do
1414
@server = TestServer.new
1515
@server.config.allowed_request_origins = %w( http://rubyonrails.com )
16+
@server.config.allow_same_origin_as_host = false
1617
end
1718

1819
teardown do
1920
@server.config.disable_request_forgery_protection = false
2021
@server.config.allowed_request_origins = []
21-
@server.config.allow_same_origin_as_host = false
22+
@server.config.allow_same_origin_as_host = true
2223
end
2324

2425
test "disable forgery protection" do

0 commit comments

Comments
 (0)
Please sign in to comment.