未验证 提交 dc6185b4 编写于 作者: A Andrew White 提交者: GitHub

Merge pull request #32054 from rails/fix-generation-of-empty-csp

Fix generation of empty content security policy
......@@ -21,10 +21,7 @@ def call(env)
return response if policy_present?(headers)
if policy = request.content_security_policy
built_policy = policy.build(request.controller_instance)
if built_policy
headers[header_name(request)] = built_policy
end
headers[header_name(request)] = policy.build(request.controller_instance)
end
response
......@@ -175,12 +172,7 @@ def upgrade_insecure_requests(enabled = true)
end
def build(context = nil)
built_directives = build_directives(context).compact
if built_directives.empty?
nil
else
built_directives.join("; ") + ";"
end
build_directives(context).compact.join("; ")
end
private
......
......@@ -8,10 +8,10 @@ def setup
end
def test_build
assert_nil @policy.build
assert_equal "", @policy.build
@policy.script_src :self
assert_equal "script-src 'self';", @policy.build
assert_equal "script-src 'self'", @policy.build
end
def test_dup
......@@ -25,34 +25,34 @@ def test_dup
def test_mappings
@policy.script_src :data
assert_equal "script-src data:;", @policy.build
assert_equal "script-src data:", @policy.build
@policy.script_src :mediastream
assert_equal "script-src mediastream:;", @policy.build
assert_equal "script-src mediastream:", @policy.build
@policy.script_src :blob
assert_equal "script-src blob:;", @policy.build
assert_equal "script-src blob:", @policy.build
@policy.script_src :filesystem
assert_equal "script-src filesystem:;", @policy.build
assert_equal "script-src filesystem:", @policy.build
@policy.script_src :self
assert_equal "script-src 'self';", @policy.build
assert_equal "script-src 'self'", @policy.build
@policy.script_src :unsafe_inline
assert_equal "script-src 'unsafe-inline';", @policy.build
assert_equal "script-src 'unsafe-inline'", @policy.build
@policy.script_src :unsafe_eval
assert_equal "script-src 'unsafe-eval';", @policy.build
assert_equal "script-src 'unsafe-eval'", @policy.build
@policy.script_src :none
assert_equal "script-src 'none';", @policy.build
assert_equal "script-src 'none'", @policy.build
@policy.script_src :strict_dynamic
assert_equal "script-src 'strict-dynamic';", @policy.build
assert_equal "script-src 'strict-dynamic'", @policy.build
@policy.script_src :none, :report_sample
assert_equal "script-src 'none' 'report-sample';", @policy.build
assert_equal "script-src 'none' 'report-sample'", @policy.build
end
def test_fetch_directives
......@@ -131,16 +131,16 @@ def test_fetch_directives
def test_document_directives
@policy.base_uri "https://example.com"
assert_match %r{base-uri https://example\.com;}, @policy.build
assert_match %r{base-uri https://example\.com}, @policy.build
@policy.plugin_types "application/x-shockwave-flash"
assert_match %r{plugin-types application/x-shockwave-flash;}, @policy.build
assert_match %r{plugin-types application/x-shockwave-flash}, @policy.build
@policy.sandbox
assert_match %r{sandbox;}, @policy.build
assert_match %r{sandbox}, @policy.build
@policy.sandbox "allow-scripts", "allow-modals"
assert_match %r{sandbox allow-scripts allow-modals;}, @policy.build
assert_match %r{sandbox allow-scripts allow-modals}, @policy.build
@policy.sandbox false
assert_no_match %r{sandbox}, @policy.build
......@@ -148,35 +148,35 @@ def test_document_directives
def test_navigation_directives
@policy.form_action :self
assert_match %r{form-action 'self';}, @policy.build
assert_match %r{form-action 'self'}, @policy.build
@policy.frame_ancestors :self
assert_match %r{frame-ancestors 'self';}, @policy.build
assert_match %r{frame-ancestors 'self'}, @policy.build
end
def test_reporting_directives
@policy.report_uri "/violations"
assert_match %r{report-uri /violations;}, @policy.build
assert_match %r{report-uri /violations}, @policy.build
end
def test_other_directives
@policy.block_all_mixed_content
assert_match %r{block-all-mixed-content;}, @policy.build
assert_match %r{block-all-mixed-content}, @policy.build
@policy.block_all_mixed_content false
assert_no_match %r{block-all-mixed-content}, @policy.build
@policy.require_sri_for :script, :style
assert_match %r{require-sri-for script style;}, @policy.build
assert_match %r{require-sri-for script style}, @policy.build
@policy.require_sri_for "script", "style"
assert_match %r{require-sri-for script style;}, @policy.build
assert_match %r{require-sri-for script style}, @policy.build
@policy.require_sri_for
assert_no_match %r{require-sri-for}, @policy.build
@policy.upgrade_insecure_requests
assert_match %r{upgrade-insecure-requests;}, @policy.build
assert_match %r{upgrade-insecure-requests}, @policy.build
@policy.upgrade_insecure_requests false
assert_no_match %r{upgrade-insecure-requests}, @policy.build
......@@ -184,13 +184,13 @@ def test_other_directives
def test_multiple_sources
@policy.script_src :self, :https
assert_equal "script-src 'self' https:;", @policy.build
assert_equal "script-src 'self' https:", @policy.build
end
def test_multiple_directives
@policy.script_src :self, :https
@policy.style_src :self, :https
assert_equal "script-src 'self' https:; style-src 'self' https:;", @policy.build
assert_equal "script-src 'self' https:; style-src 'self' https:", @policy.build
end
def test_dynamic_directives
......@@ -198,12 +198,12 @@ def test_dynamic_directives
controller = Struct.new(:request).new(request)
@policy.script_src -> { request.host }
assert_equal "script-src www.example.com;", @policy.build(controller)
assert_equal "script-src www.example.com", @policy.build(controller)
end
def test_mixed_static_and_dynamic_directives
@policy.script_src :self, -> { "foo.com" }, "bar.com"
assert_equal "script-src 'self' foo.com bar.com;", @policy.build(Object.new)
assert_equal "script-src 'self' foo.com bar.com", @policy.build(Object.new)
end
def test_invalid_directive_source
......@@ -271,10 +271,6 @@ def report_only
head :ok
end
def empty_policy
head :ok
end
private
def condition?
params[:condition] == "true"
......@@ -288,14 +284,12 @@ def condition?
get "/inline", to: "policy#inline"
get "/conditional", to: "policy#conditional"
get "/report-only", to: "policy#report_only"
get "/empty-policy", to: "policy#empty_policy"
end
end
POLICY = ActionDispatch::ContentSecurityPolicy.new do |p|
p.default_src :self
end
EMPTY_POLICY = ActionDispatch::ContentSecurityPolicy.new
class PolicyConfigMiddleware
def initialize(app)
......@@ -303,12 +297,7 @@ def initialize(app)
end
def call(env)
env["action_dispatch.content_security_policy"] =
if env["PATH_INFO"] == "/empty-policy"
EMPTY_POLICY
else
POLICY
end
env["action_dispatch.content_security_policy"] = POLICY
env["action_dispatch.content_security_policy_report_only"] = false
env["action_dispatch.show_exceptions"] = false
......@@ -327,32 +316,25 @@ def app
def test_generates_content_security_policy_header
get "/"
assert_policy "default-src 'self';"
assert_policy "default-src 'self'"
end
def test_generates_inline_content_security_policy
get "/inline"
assert_policy "default-src https://example.com;"
assert_policy "default-src https://example.com"
end
def test_generates_conditional_content_security_policy
get "/conditional", params: { condition: "true" }
assert_policy "default-src https://true.example.com;"
assert_policy "default-src https://true.example.com"
get "/conditional", params: { condition: "false" }
assert_policy "default-src https://false.example.com;"
assert_policy "default-src https://false.example.com"
end
def test_generates_report_only_content_security_policy
get "/report-only"
assert_policy "default-src 'self'; report-uri /violations;", report_only: true
end
def test_empty_policy
get "/empty-policy"
assert_response :success
assert_not response.headers.key?("Content-Security-Policy")
assert_not response.headers.key?("Content-Security-Policy-Report-Only")
assert_policy "default-src 'self'; report-uri /violations", report_only: true
end
private
......
......@@ -241,7 +241,11 @@ def annotations
end
def content_security_policy(&block)
@content_security_policy ||= ActionDispatch::ContentSecurityPolicy.new(&block)
if block_given?
@content_security_policy = ActionDispatch::ContentSecurityPolicy.new(&block)
else
@content_security_policy
end
end
class Custom #:nodoc:
......
......@@ -16,7 +16,7 @@ def teardown
teardown_app
end
test "default content security policy is empty" do
test "default content security policy is nil" do
controller :pages, <<-RUBY
class PagesController < ApplicationController
def index
......@@ -34,7 +34,33 @@ def index
app("development")
get "/"
assert_not last_response.headers.key?("Content-Security-Policy")
assert_nil last_response.headers["Content-Security-Policy"]
end
test "empty content security policy is generated" do
controller :pages, <<-RUBY
class PagesController < ApplicationController
def index
render html: "<h1>Welcome to Rails!</h1>"
end
end
RUBY
app_file "config/initializers/content_security_policy.rb", <<-RUBY
Rails.application.config.content_security_policy do |p|
end
RUBY
app_file "config/routes.rb", <<-RUBY
Rails.application.routes.draw do
root to: "pages#index"
end
RUBY
app("development")
get "/"
assert_policy ""
end
test "global content security policy in an initializer" do
......@@ -61,7 +87,7 @@ def index
app("development")
get "/"
assert_policy "default-src 'self' https:;"
assert_policy "default-src 'self' https:"
end
test "global report only content security policy in an initializer" do
......@@ -90,7 +116,7 @@ def index
app("development")
get "/"
assert_policy "default-src 'self' https:;", report_only: true
assert_policy "default-src 'self' https:", report_only: true
end
test "override content security policy in a controller" do
......@@ -121,7 +147,7 @@ def index
app("development")
get "/"
assert_policy "default-src https://example.com;"
assert_policy "default-src https://example.com"
end
test "override content security policy to report only in a controller" do
......@@ -150,7 +176,7 @@ def index
app("development")
get "/"
assert_policy "default-src 'self' https:;", report_only: true
assert_policy "default-src 'self' https:", report_only: true
end
test "global content security policy added to rack app" do
......@@ -174,7 +200,7 @@ def index
app("development")
get "/"
assert_policy "default-src 'self' https:;"
assert_policy "default-src 'self' https:"
end
private
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册