From 47013a7126a92e1f2890b68e0fd2e7ba1b77c97c Mon Sep 17 00:00:00 2001 From: Yaroslav Markin Date: Tue, 17 Apr 2018 18:05:12 +0300 Subject: Add the `nonce: true` option for `javascript_include_tag` helper. --- actionview/CHANGELOG.md | 6 ++++++ actionview/lib/action_view/helpers/asset_tag_helper.rb | 8 ++++++++ actionview/test/template/asset_tag_helper_test.rb | 8 ++++++++ guides/source/security.md | 6 ++++++ 4 files changed, 28 insertions(+) diff --git a/actionview/CHANGELOG.md b/actionview/CHANGELOG.md index 6bb1efb0ac..d833f9cd98 100644 --- a/actionview/CHANGELOG.md +++ b/actionview/CHANGELOG.md @@ -1,3 +1,9 @@ +* Add the `nonce: true` option for `javascript_include_tag` helper to + support automatic nonce generation for Content Security Policy. + Works the same way as `javascript_tag nonce: true` does. + + *Yaroslav Markin* + * Remove `ActionView::Helpers::RecordTagHelper`. *Yoshiyuki Hirano* diff --git a/actionview/lib/action_view/helpers/asset_tag_helper.rb b/actionview/lib/action_view/helpers/asset_tag_helper.rb index 06fa1875fc..257080d902 100644 --- a/actionview/lib/action_view/helpers/asset_tag_helper.rb +++ b/actionview/lib/action_view/helpers/asset_tag_helper.rb @@ -55,6 +55,8 @@ module ActionView # that path. # * :skip_pipeline - This option is used to bypass the asset pipeline # when it is set to true. + # * :nonce - When set to true, adds an automatic nonce value if + # you have Content Security Policy enabled. # # ==== Examples # @@ -79,6 +81,9 @@ module ActionView # # javascript_include_tag "http://www.example.com/xmlhr.js" # # => + # + # javascript_include_tag "http://www.example.com/xmlhr.js", nonce: true + # # => def javascript_include_tag(*sources) options = sources.extract_options!.stringify_keys path_options = options.extract!("protocol", "extname", "host", "skip_pipeline").symbolize_keys @@ -90,6 +95,9 @@ module ActionView tag_options = { "src" => href }.merge!(options) + if tag_options["nonce"] == true + tag_options["nonce"] = content_security_policy_nonce + end content_tag("script".freeze, "", tag_options) }.join("\n").html_safe diff --git a/actionview/test/template/asset_tag_helper_test.rb b/actionview/test/template/asset_tag_helper_test.rb index 6d98eacfb8..e68f03d1f4 100644 --- a/actionview/test/template/asset_tag_helper_test.rb +++ b/actionview/test/template/asset_tag_helper_test.rb @@ -29,6 +29,10 @@ class AssetTagHelperTest < ActionView::TestCase "http://www.example.com" end + def content_security_policy_nonce + "iyhD0Yc0W+c=" + end + AssetPathToTag = { %(asset_path("")) => %(), %(asset_path(" ")) => %(), @@ -421,6 +425,10 @@ class AssetTagHelperTest < ActionView::TestCase assert_dom_equal %(), javascript_include_tag("prototype") end + def test_javascript_include_tag_nonce + assert_dom_equal %(), javascript_include_tag("bank", nonce: true) + end + def test_stylesheet_path StylePathToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) } end diff --git a/guides/source/security.md b/guides/source/security.md index a21526d895..3ac50fb147 100644 --- a/guides/source/security.md +++ b/guides/source/security.md @@ -1182,6 +1182,12 @@ as part of `html_options`. Example: <% end -%> ``` +The same works with `javascript_include_tag`: + +```html+erb +<%= javascript_include_tag "script", nonce: true %> +``` + Use [`csp_meta_tag`](http://api.rubyonrails.org/classes/ActionView/Helpers/CspHelper.html#method-i-csp_meta_tag) helper to create a meta tag "csp-nonce" with the per-session nonce value for allowing inline `