Skip to content

Commit

Permalink
Merge pull request #32607 from yaroslav/feature/nonce-for-javascript_…
Browse files Browse the repository at this point in the history
…include_tag

Add the `nonce: true` option for `javascript_include_tag` helper.
  • Loading branch information
pixeltrix committed Apr 18, 2018
2 parents 7bcb04c + 47013a7 commit 185fce1
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 0 deletions.
6 changes: 6 additions & 0 deletions 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*
Expand Down
8 changes: 8 additions & 0 deletions actionview/lib/action_view/helpers/asset_tag_helper.rb
Expand Up @@ -55,6 +55,8 @@ module AssetTagHelper
# that path.
# * <tt>:skip_pipeline</tt> - This option is used to bypass the asset pipeline
# when it is set to true.
# * <tt>:nonce<tt> - When set to true, adds an automatic nonce value if
# you have Content Security Policy enabled.
#
# ==== Examples
#
Expand All @@ -79,6 +81,9 @@ module AssetTagHelper
#
# javascript_include_tag "http://www.example.com/xmlhr.js"
# # => <script src="http://www.example.com/xmlhr.js"></script>
#
# javascript_include_tag "http://www.example.com/xmlhr.js", nonce: true
# # => <script src="http://www.example.com/xmlhr.js" nonce="..."></script>
def javascript_include_tag(*sources)
options = sources.extract_options!.stringify_keys
path_options = options.extract!("protocol", "extname", "host", "skip_pipeline").symbolize_keys
Expand All @@ -90,6 +95,9 @@ def javascript_include_tag(*sources)
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

Expand Down
8 changes: 8 additions & 0 deletions actionview/test/template/asset_tag_helper_test.rb
Expand Up @@ -29,6 +29,10 @@ def url_for(*args)
"http://www.example.com"
end

def content_security_policy_nonce
"iyhD0Yc0W+c="
end

AssetPathToTag = {
%(asset_path("")) => %(),
%(asset_path(" ")) => %(),
Expand Down Expand Up @@ -421,6 +425,10 @@ def test_javascript_include_tag_default_protocol
assert_dom_equal %(<script src="//assets.example.com/javascripts/prototype.js"></script>), javascript_include_tag("prototype")
end

def test_javascript_include_tag_nonce
assert_dom_equal %(<script src="/javascripts/bank.js" nonce="iyhD0Yc0W+c="></script>), javascript_include_tag("bank", nonce: true)
end

def test_stylesheet_path
StylePathToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) }
end
Expand Down
6 changes: 6 additions & 0 deletions guides/source/security.md
Expand Up @@ -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 `<script>` tags.
Expand Down

0 comments on commit 185fce1

Please sign in to comment.