Skip to content

Commit e7df6f7

Browse files
authored
feat: Added nonce support (#86)
1 parent 677428b commit e7df6f7

5 files changed

Lines changed: 43 additions & 24 deletions

File tree

README.md

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010

1111
To use phraseapp-in-context-editor-ruby with your application you have to:
1212

13-
* Sign up for a Phrase account: [https://app.phrase.com/signup](https://app.phrase.com/signup)
14-
* Use the excellent [i18n](https://github.com/ruby-i18n/i18n) gem also used by [Rails](https://guides.rubyonrails.org/i18n.html)
13+
- Sign up for a Phrase account: [https://app.phrase.com/signup](https://app.phrase.com/signup)
14+
- Use the excellent [i18n](https://github.com/ruby-i18n/i18n) gem also used by [Rails](https://guides.rubyonrails.org/i18n.html)
1515

1616
### Demo
1717

@@ -21,11 +21,13 @@ Login via the demo credentials `demo@phrase.com` / `phrase`
2121
### Installation
2222

2323
#### NOTE: You can not use the old version of the ICE with integration versions of >2.0.0, you have to instead use 1.x.x versions as before
24+
2425
#### via Gem
2526

2627
```bash
2728
gem install phraseapp-in-context-editor-ruby
2829
```
30+
2931
#### via Bundler
3032

3133
Add it to your `Gemfile`
@@ -84,13 +86,26 @@ Old version of the ICE is not available since version 2.0.0. If you still would
8486
#### Using the US Datacenter with ICE
8587

8688
In addition to the settings in your `config/initializers/phraseapp_in_context_editor.rb`, set the US datacenter to enable the ICE to work with the US endpoints.
89+
8790
```ruby
8891
config.enabled = true
8992
config.project_id = "YOUR_PROJECT_ID"
9093
config.account_id = "YOUR_ACCOUNT_ID"
9194
config.datacenter = "us"
9295
```
9396

97+
#### Using with CSP
98+
99+
The script will automatically get the nonce from `content_security_policy_nonce`
100+
The content_security_policy.rb has to have `:strict_dynamic` for `policy.script_src` since we are loading more scripts dynamically because of our way of deploying
101+
102+
```ruby
103+
policy.script_src :self, :https, :strict_dynamic
104+
policy.style_src :self, :https
105+
```
106+
107+
The `config.content_security_policy_nonce_directives = %w[script-src style-src]` can include `style-src` but this _might_ break some styling in some cases
108+
94109
### Browser support
95110

96111
This library might not work out of the box for some older browser or IE11. We recommend to add [Babel](https://github.com/babel/babel) to the build pipeline if those browser need to be supported.

examples/demo/app/views/layouts/application.html.erb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<%= csrf_meta_tags %>
77
<%= csp_meta_tag %>
88

9-
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
9+
<%= stylesheet_link_tag "application", "data-turbo-track": "reload", nonce: true %>
1010
<%= javascript_importmap_tags %>
1111
<%= load_in_context_editor %>
1212
</head>

examples/demo/config/initializers/content_security_policy.rb

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,22 @@
44
# See the Securing Rails Applications Guide for more information:
55
# https://guides.rubyonrails.org/security.html#content-security-policy-header
66

7-
# Rails.application.configure do
8-
# config.content_security_policy do |policy|
9-
# policy.default_src :self, :https
10-
# policy.font_src :self, :https, :data
11-
# policy.img_src :self, :https, :data
12-
# policy.object_src :none
13-
# policy.script_src :self, :https
14-
# policy.style_src :self, :https
15-
# # Specify URI for violation reports
16-
# # policy.report_uri "/csp-violation-report-endpoint"
17-
# end
18-
#
19-
# # Generate session nonces for permitted importmap and inline scripts
20-
# config.content_security_policy_nonce_generator = ->(request) { request.session.id.to_s }
21-
# config.content_security_policy_nonce_directives = %w(script-src)
22-
#
23-
# # Report violations without enforcing the policy.
24-
# # config.content_security_policy_report_only = true
25-
# end
7+
Rails.application.configure do
8+
config.content_security_policy do |policy|
9+
policy.default_src :self, :https
10+
policy.font_src :self, :https, :data
11+
policy.img_src :self, :https, :data
12+
policy.object_src :none
13+
policy.script_src :self, :https, :strict_dynamic
14+
policy.style_src :self, :https
15+
# Specify URI for violation reports
16+
# policy.report_uri "/csp-violation-report-endpoint"
17+
end
18+
19+
# Generate session nonces for permitted importmap and inline scripts
20+
config.content_security_policy_nonce_generator = ->(request) { request.session.id.to_s }
21+
config.content_security_policy_nonce_directives = %w[script-src style-src]
22+
23+
# Report violations without enforcing the policy.
24+
# config.content_security_policy_report_only = true
25+
end

lib/phraseapp-in-context-editor-ruby/view_helpers.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def load_in_context_editor(opts = {})
2222
}.merge(opts)
2323

2424
snippet = <<-EOS
25-
<script>
25+
<script nonce='#{content_security_policy_nonce}'>
2626
window.PHRASEAPP_CONFIG = #{configuration.to_json};
2727
(function() {
2828
let phraseapp = document.createElement('script');

spec/phraseapp-in-context-editor-ruby/view_helpers_spec.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
require "phraseapp-in-context-editor-ruby"
33
require "phraseapp-in-context-editor-ruby/view_helpers"
44

5+
def content_security_policy_nonce
6+
"some_nonce"
7+
end
8+
59
describe PhraseApp::InContextEditor::ViewHelpers do
610
before(:all) do
711
class Helpers
@@ -20,7 +24,7 @@ class Helpers
2024
before(:each) { PhraseApp::InContextEditor.config.enabled = true }
2125

2226
describe "has right ICE bundle address" do
23-
it { is_expected.to include("<script>") }
27+
it { is_expected.to include("<script nonce='some_nonce'>") }
2428
it { is_expected.to include("https://d2bgdldl6xit7z.cloudfront.net/latest/ice/index.js") }
2529
it { is_expected.to include("</script>") }
2630
end

0 commit comments

Comments
 (0)