From c836c93b818ee6a56d3a8ece36eb380f42ba5bf3 Mon Sep 17 00:00:00 2001 From: evazion Date: Tue, 15 Dec 2020 03:43:13 -0600 Subject: [PATCH] autocomplete: don't send cookies in publicly cached responses. Fix session cookies being sent in publicly cached /autocomplete.json responses. We can't set any cookies in a response that is being publicly cached, otherwise they'll be visible to other users. If a user's session cookies were to be cached, then it would allow their account to be stolen. In reality, well-behaved caches like Cloudflare will simply refuse to cache responses that contain cookies to avoid this scenario. https://support.cloudflare.com/hc/en-us/articles/200172516-Understanding-Cloudflare-s-CDN: BYPASS is returned when enabling Origin Cache-Control. Cloudflare also sets BYPASS when your origin web server sends cookies in the response header. --- app/controllers/application_controller.rb | 9 +++++++++ test/functional/autocomplete_controller_test.rb | 8 ++++++++ 2 files changed, 17 insertions(+) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 9afec6b03..8f6faeb53 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -15,6 +15,7 @@ class ApplicationController < ActionController::Base before_action :set_variant before_action :add_headers before_action :cause_error + after_action :skip_session_if_publicly_cached after_action :reset_current_user layout "default" @@ -148,6 +149,14 @@ class ApplicationController < ActionController::Base CurrentUser.root_url = root_url.chomp("/") end + # Skip setting the session cookie if the response is being publicly cached to + # prevent the user's session cookie from being leaked to other users. + def skip_session_if_publicly_cached + if response.cache_control[:public] == true + request.session_options[:skip] = true + end + end + def set_variant request.variant = params[:variant].try(:to_sym) end diff --git a/test/functional/autocomplete_controller_test.rb b/test/functional/autocomplete_controller_test.rb index 4dd62ee1a..ae372ab1f 100644 --- a/test/functional/autocomplete_controller_test.rb +++ b/test/functional/autocomplete_controller_test.rb @@ -34,6 +34,14 @@ class AutocompleteControllerTest < ActionDispatch::IntegrationTest assert_autocomplete_equals(["rating:safe"], "rating:s", "tag_query") assert_autocomplete_equals(["rating:safe"], "-rating:s", "tag_query") end + + should "not set session cookies when the response is publicly cached" do + get autocomplete_index_path(search: { query: "azur", type: "tag_query" }), as: :json + + assert_response :success + assert_equal(true, response.cache_control[:public]) + assert_equal({}, response.cookies) + end end end end