diff --git a/lib/xray/middleware.rb b/lib/xray/middleware.rb
index 53a6b8e..6473967 100644
--- a/lib/xray/middleware.rb
+++ b/lib/xray/middleware.rb
@@ -111,10 +111,15 @@ def script_matcher(script_name)
/x
end
+ def nonce_from_meta_tag(html)
+ html[/= 5.2
+ content_security_policy only: :strict_csp do |policy|
+ policy.script_src :self, :strict_dynamic
+ end
+ end
+
def root
end
+ def strict_csp
+ render :root
+ end
+
# For the tests
def non_html
render json: {foo: 'bar'}
diff --git a/spec/dummy/app/views/layouts/application.html.erb b/spec/dummy/app/views/layouts/application.html.erb
index b495424..61724e2 100644
--- a/spec/dummy/app/views/layouts/application.html.erb
+++ b/spec/dummy/app/views/layouts/application.html.erb
@@ -2,9 +2,10 @@
Xray
- <%= stylesheet_link_tag "application", :media => "all" %>
- <%= javascript_include_tag "application" %>
+ <%= stylesheet_link_tag "application", media: "all" %>
+ <%= javascript_include_tag "application", nonce: true %>
<%= csrf_meta_tags %>
+ <%= csp_meta_tag %>
diff --git a/spec/dummy/config/initializers/content_security_policy.rb b/spec/dummy/config/initializers/content_security_policy.rb
new file mode 100644
index 0000000..397abc9
--- /dev/null
+++ b/spec/dummy/config/initializers/content_security_policy.rb
@@ -0,0 +1,7 @@
+if Gem.loaded_specs['rails'].version >= Gem::Version.new('5.2.0')
+ Rails.application.config.content_security_policy do |policy|
+ # Empty. Only need one endpoint (/strict_csp) to use a strict CSP in our tests.
+ end
+
+ Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) }
+end
diff --git a/spec/xray/e2e_spec.rb b/spec/xray/e2e_spec.rb
index 56b1b67..62127a1 100644
--- a/spec/xray/e2e_spec.rb
+++ b/spec/xray/e2e_spec.rb
@@ -6,7 +6,18 @@
expect_to_work
end
+ if Gem.loaded_specs['rails'].version >= Gem::Version.new('5.2.0')
+ it "works when using a strict CSP" do
+ visit '/strict_csp'
+ expect_to_work
+ end
+ end
+
def expect_to_work
+ if Gem.loaded_specs['rails'].version >= Gem::Version.new('5.2.0')
+ expect(page).to have_selector('script[src^="/assets/xray"][nonce]')
+ expect(page.find('script[src^="/assets/xray"]')[:nonce]).to eq page.find('meta[name="csp-nonce"]')[:content]
+ end
expect(page).to have_selector('#xray-bar')
expect(page).to have_no_selector('.xray-specimen-handle.TemplateSpecimen', text: 'root.html.erb')
diff --git a/spec/xray/middleware_spec.rb b/spec/xray/middleware_spec.rb
index 84ef1bd..f5d3cdb 100644
--- a/spec/xray/middleware_spec.rb
+++ b/spec/xray/middleware_spec.rb
@@ -95,6 +95,14 @@ def mock_response(status, content_type, body)
expect(page).to have_selector('script[src^="/assets/xray"]')
end
+ if Gem.loaded_specs['rails'].version >= Gem::Version.new('5.2.0')
+ it "adds nonce to the script tag" do
+ visit '/'
+ expect(page).to have_selector('script[src^="/assets/xray"][nonce]')
+ expect(page.find('script[src^="/assets/xray"]')[:nonce]).to eq page.find('meta[name="csp-nonce"]')[:content]
+ end
+ end
+
it "injects the xray bar into the response" do
visit '/'
expect(page).to have_selector('#xray-bar')