From 8198d7c4accad0b6ba956b9d59528534a289866b Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 8 Mar 2022 13:23:15 -0800 Subject: [PATCH] Merge pull request #44635 from imtayadeway/tjw/api-csp-i Generate content security policy for non-HTML responses --- actionpack/CHANGELOG.md | 4 ++++ .../http/content_security_policy.rb | 7 ------- .../test/dispatch/content_security_policy_test.rb | 15 +++++++++++++++ 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index b358c400fc033..db19ebe19cc0b 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,3 +1,7 @@ +* Allow Content Security Policy DSL to generate for API responses. + + *Tim Wade* + ## Rails 7.0.2.3 (March 08, 2022) ## * No changes. diff --git a/actionpack/lib/action_dispatch/http/content_security_policy.rb b/actionpack/lib/action_dispatch/http/content_security_policy.rb index 0ca2f79e2ff57..ecb28498e3e08 100644 --- a/actionpack/lib/action_dispatch/http/content_security_policy.rb +++ b/actionpack/lib/action_dispatch/http/content_security_policy.rb @@ -17,7 +17,6 @@ def call(env) request = ActionDispatch::Request.new env _, headers, _ = response = @app.call(env) - return response unless html_response?(headers) return response if policy_present?(headers) if policy = request.content_security_policy @@ -31,12 +30,6 @@ def call(env) end private - def html_response?(headers) - if content_type = headers[CONTENT_TYPE] - /html/.match?(content_type) - end - end - def header_name(request) if request.content_security_policy_report_only POLICY_REPORT_ONLY diff --git a/actionpack/test/dispatch/content_security_policy_test.rb b/actionpack/test/dispatch/content_security_policy_test.rb index f95920b145098..5b3b4ef1ae117 100644 --- a/actionpack/test/dispatch/content_security_policy_test.rb +++ b/actionpack/test/dispatch/content_security_policy_test.rb @@ -395,6 +395,11 @@ class PolicyController < ActionController::Base content_security_policy_report_only only: :report_only + content_security_policy only: :api do |p| + p.default_src :none + p.frame_ancestors :none + end + def index head :ok end @@ -423,6 +428,10 @@ def no_policy head :ok end + def api + render json: {} + end + private def condition? params[:condition] == "true" @@ -439,6 +448,7 @@ def condition? get "/script-src", to: "policy#script_src" get "/style-src", to: "policy#style_src" get "/no-policy", to: "policy#no_policy" + get "/api", to: "policy#api" end end @@ -510,6 +520,11 @@ def test_generates_no_content_security_policy assert_nil response.headers["Content-Security-Policy-Report-Only"] end + def test_generates_api_security_policy + get "/api" + assert_policy "default-src 'none'; frame-ancestors 'none'" + end + private def assert_policy(expected, report_only: false) assert_response :success