diff options
author | Andrew White <pixeltrix@users.noreply.github.com> | 2018-02-22 15:32:23 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-02-22 15:32:23 +0000 |
commit | e20742f12b362676e8f69fe68c3193ad80a90172 (patch) | |
tree | 6e8a3c3b0206673cc7a27d67750af0f053acc96d /actionpack/lib | |
parent | 1c36aa71bd352e3704f424991f77c780853b3ac4 (diff) | |
parent | 31abee0341cb9d19f0234da7b42dddbabfcd1d4a (diff) | |
download | rails-e20742f12b362676e8f69fe68c3193ad80a90172.tar.gz rails-e20742f12b362676e8f69fe68c3193ad80a90172.tar.bz2 rails-e20742f12b362676e8f69fe68c3193ad80a90172.zip |
Merge pull request #32018 from rails/add-nonce-support-to-csp
Add support for automatic nonce generation for Rails UJS
Diffstat (limited to 'actionpack/lib')
-rw-r--r-- | actionpack/lib/action_controller/metal/content_security_policy.rb | 18 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/http/content_security_policy.rb | 32 |
2 files changed, 50 insertions, 0 deletions
diff --git a/actionpack/lib/action_controller/metal/content_security_policy.rb b/actionpack/lib/action_controller/metal/content_security_policy.rb index 48a7109bea..95f2f3242d 100644 --- a/actionpack/lib/action_controller/metal/content_security_policy.rb +++ b/actionpack/lib/action_controller/metal/content_security_policy.rb @@ -5,6 +5,14 @@ module ActionController #:nodoc: # TODO: Documentation extend ActiveSupport::Concern + include AbstractController::Helpers + include AbstractController::Callbacks + + included do + helper_method :content_security_policy? + helper_method :content_security_policy_nonce + end + module ClassMethods def content_security_policy(**options, &block) before_action(options) do @@ -22,5 +30,15 @@ module ActionController #:nodoc: end end end + + private + + def content_security_policy? + request.content_security_policy + end + + def content_security_policy_nonce + request.content_security_policy_nonce + end end end diff --git a/actionpack/lib/action_dispatch/http/content_security_policy.rb b/actionpack/lib/action_dispatch/http/content_security_policy.rb index ffac3b8d99..a3407c9698 100644 --- a/actionpack/lib/action_dispatch/http/content_security_policy.rb +++ b/actionpack/lib/action_dispatch/http/content_security_policy.rb @@ -21,6 +21,12 @@ module ActionDispatch #:nodoc: return response if policy_present?(headers) if policy = request.content_security_policy + if policy.directives["script-src"] + if nonce = request.content_security_policy_nonce + policy.directives["script-src"] << "'nonce-#{nonce}'" + end + end + headers[header_name(request)] = policy.build(request.controller_instance) end @@ -51,6 +57,8 @@ module ActionDispatch #:nodoc: module Request POLICY = "action_dispatch.content_security_policy".freeze POLICY_REPORT_ONLY = "action_dispatch.content_security_policy_report_only".freeze + NONCE_GENERATOR = "action_dispatch.content_security_policy_nonce_generator".freeze + NONCE = "action_dispatch.content_security_policy_nonce".freeze def content_security_policy get_header(POLICY) @@ -67,6 +75,30 @@ module ActionDispatch #:nodoc: def content_security_policy_report_only=(value) set_header(POLICY_REPORT_ONLY, value) end + + def content_security_policy_nonce_generator + get_header(NONCE_GENERATOR) + end + + def content_security_policy_nonce_generator=(generator) + set_header(NONCE_GENERATOR, generator) + end + + def content_security_policy_nonce + if content_security_policy_nonce_generator + if nonce = get_header(NONCE) + nonce + else + set_header(NONCE, generate_content_security_policy_nonce) + end + end + end + + private + + def generate_content_security_policy_nonce + content_security_policy_nonce_generator.call(self) + end end MAPPINGS = { |