From 803f87567f0cd11295f4155189417225747e115c Mon Sep 17 00:00:00 2001 From: Tim Wade Date: Tue, 16 Jun 2020 10:54:35 -0700 Subject: [PATCH 1/2] Generate content security policy for non-HTML responses One feature of the content security policy DSL, though undocumented, is that it will not generate headers for non-HTML responses, even if a configuration is explicitly provided. While it may not seem obvious that anyone would want to send this header in an API response, Mozilla Observatory, for instance, recommends the following for API responses: `Content-Security-Policy: default-src 'none'; frame-ancestors 'none'` (source: https://observatory.mozilla.org/faq/) The Secure Headers gem also makes recommendations about the content security policy for API responses: https://github.com/github/secure_headers#api-configurations As such, this removes the HTML guard clause from the `ContentSecurityPolicy` middleware. --- actionpack/CHANGELOG.md | 3 +++ .../http/content_security_policy.rb | 7 ------- .../test/dispatch/content_security_policy_test.rb | 15 +++++++++++++++ 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index 73ebe35b2236d..12425f8757dc1 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,3 +1,6 @@ +* Allow Content Security Policy DSL to generate for API responses. + *Tim Wade* + * Fix `authenticate_with_http_basic` to allow for missing password. Before Rails 7.0 it was possible to handle basic authentication with only a username. diff --git a/actionpack/lib/action_dispatch/http/content_security_policy.rb b/actionpack/lib/action_dispatch/http/content_security_policy.rb index 9b63a157626b6..f544e18e94ffc 100644 --- a/actionpack/lib/action_dispatch/http/content_security_policy.rb +++ b/actionpack/lib/action_dispatch/http/content_security_policy.rb @@ -35,7 +35,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 @@ -49,12 +48,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 0fd1868a3f94f..b9ec78645c0f8 100644 --- a/actionpack/test/dispatch/content_security_policy_test.rb +++ b/actionpack/test/dispatch/content_security_policy_test.rb @@ -403,6 +403,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 @@ -431,6 +436,10 @@ def no_policy head :ok end + def api + render json: {} + end + private def condition? params[:condition] == "true" @@ -447,6 +456,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 @@ -518,6 +528,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 From acf7e0d2fe8df55e070a8e511622e91d49544d62 Mon Sep 17 00:00:00 2001 From: Tim Wade Date: Mon, 7 Mar 2022 16:33:00 -0800 Subject: [PATCH 2/2] Update actionpack/CHANGELOG.md Co-authored-by: Alex Ghiculescu --- actionpack/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index 12425f8757dc1..115a6cc42e10b 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,4 +1,5 @@ * Allow Content Security Policy DSL to generate for API responses. + *Tim Wade* * Fix `authenticate_with_http_basic` to allow for missing password.