diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index d44e28105ae..c5f613d9aa7 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1008,7 +1008,14 @@ class ApplicationController < ActionController::Base end def set_cross_origin_opener_policy_header - response.headers["Cross-Origin-Opener-Policy"] = SiteSetting.cross_origin_opener_policy_header + response.headers["Cross-Origin-Opener-Policy"] = if SiteSetting + .cross_origin_opener_unsafe_none_referrers + .split("|") + .include?(request.referrer&.split("://")&.last) + "unsafe-none" + else + SiteSetting.cross_origin_opener_policy_header + end end protected diff --git a/config/site_settings.yml b/config/site_settings.yml index cd693788114..c77fb42eaaa 100644 --- a/config/site_settings.yml +++ b/config/site_settings.yml @@ -2052,6 +2052,10 @@ security: - "same-origin" - "same-origin-allow-popups" hidden: true + cross_origin_opener_unsafe_none_referrers: + default: "" + type: host_list + hidden: true onebox: post_onebox_maxlength: diff --git a/spec/requests/application_controller_spec.rb b/spec/requests/application_controller_spec.rb index 621db5936df..a1167032c11 100644 --- a/spec/requests/application_controller_spec.rb +++ b/spec/requests/application_controller_spec.rb @@ -547,6 +547,35 @@ RSpec.describe ApplicationController do expect(response.headers["Cross-Origin-Opener-Policy"]).to eq("unsafe-none") end end + + describe "when `cross_origin_unsafe_none_referrers` site setting has been set" do + before do + SiteSetting.cross_origin_opener_policy_header = "same-origin" + SiteSetting.cross_origin_opener_unsafe_none_referrers = + "meta.discourse.org|try.discourse.org" + end + + it "sets `Cross-Origin-Opener-Policy` to `unsafe-none` for a listed referrer" do + get "/latest", headers: { "HTTP_REFERER" => "meta.discourse.org" } + + expect(response.status).to eq(200) + expect(response.headers["Cross-Origin-Opener-Policy"]).to eq("unsafe-none") + end + + it "sets `Cross-Origin-Opener-Policy` to configured value for a non-listed referrer" do + get "/latest", headers: { "HTTP_REFERER" => "www.discourse.org" } + + expect(response.status).to eq(200) + expect(response.headers["Cross-Origin-Opener-Policy"]).to eq("same-origin") + end + + it "sets `Cross-Origin-Opener-Policy` to configured value when referrer is missing" do + get "/latest" + + expect(response.status).to eq(200) + expect(response.headers["Cross-Origin-Opener-Policy"]).to eq("same-origin") + end + end end describe "splash_screen" do