Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SecureHeaders fixes #478

Merged
merged 8 commits into from
Aug 31, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion gemfiles/rails50.gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ end

# We need last sinatra that uses rack 2.x
gem 'sinatra', :git => 'https://github.com/sinatra/sinatra'
gem 'rack-protection', :git => 'https://github.com/sinatra/rack-protection'
gem 'resque'
gem 'delayed_job', :require => false
gem 'redis'
Expand Down
8 changes: 7 additions & 1 deletion lib/rollbar/middleware/js.rb
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ def js_snippet
end

def script_tag(content, env)
if defined?(::SecureHeaders) && ::SecureHeaders.respond_to?(:content_security_policy_script_nonce)
if append_nonce?
nonce = ::SecureHeaders.content_security_policy_script_nonce(::Rack::Request.new(env))
script_tag_content = "\n<script type=\"text/javascript\" nonce=\"#{nonce}\">#{content}</script>"
else
Expand All @@ -130,6 +130,12 @@ def html_safe_if_needed(string)
string = string.html_safe if string.respond_to?(:html_safe)
string
end

def append_nonce?
defined?(::SecureHeaders) && ::SecureHeaders.respond_to?(:content_security_policy_script_nonce) &&
defined?(::SecureHeaders::Configuration) &&
!::SecureHeaders::Configuration.get.current_csp[:script_src].to_a.include?("'unsafe-inline'")
end
end
end
end
4 changes: 2 additions & 2 deletions lib/rollbar/plugins/rails.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ module Frameworks
# customer is using SecureHeaders > 3.0
class Rails
def load(plugin)
plugin_execute = plugin_execute_proc(plugin)
plugin_execute = plugin_execute_proc_body(plugin)

return after_secure_headers(&plugin_execute) if secure_headers_middleware?

Expand All @@ -42,7 +42,7 @@ def after_secure_headers(&block)
Rollbar::Railtie.initializer('rollbar.js.frameworks.rails', :after => 'secure_headers.middleware', &block)
end

def plugin_execute_proc(plugin)
def plugin_execute_proc_body(plugin)
proc do
plugin.execute do
if Rollbar.configuration.js_enabled
Expand Down
23 changes: 23 additions & 0 deletions spec/rollbar/middleware/js_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@
before do
Object.const_set('SecureHeaders', Module.new)
SecureHeaders.const_set('VERSION', '3.0.0')
SecureHeaders.const_set('Configuration', Module.new {
def self.get
end
})
allow(SecureHeaders).to receive(:content_security_policy_script_nonce) { 'lorem-ipsum-nonce' }
end

Expand All @@ -115,13 +119,32 @@
end

it 'renders the snippet and config in the response with nonce in script tag when SecureHeaders installed' do
secure_headers_config = double(:configuration, :current_csp => {})
allow(SecureHeaders::Configuration).to receive(:get).and_return(secure_headers_config)
res_status, res_headers, response = subject.call(env)

new_body = response.body.join

expect(new_body).to include('<script type="text/javascript" nonce="lorem-ipsum-nonce">')
expect(new_body).to include("var _rollbarConfig = #{config[:options].to_json};")
expect(new_body).to include(snippet)
end

it 'renders the snippet in the response without nonce if SecureHeaders script_src includes \'unsafe-inline\'' do
secure_headers_config = double(:configuration, :current_csp => {
:script_src => %w('unsafe-inline')
})
allow(SecureHeaders::Configuration).to receive(:get).and_return(secure_headers_config)

res_status, res_headers, response = subject.call(env)
new_body = response.body.join

expect(new_body).to include('<script type="text/javascript">')
expect(new_body).to include("var _rollbarConfig = #{config[:options].to_json};")
expect(new_body).to include(snippet)

SecureHeaders.send(:remove_const, 'Configuration')
end
end

context 'having a html 200 response and SecureHeaders < 3.0.0 defined' do
Expand Down