diff --git a/config/initializers/secure_headers.rb b/config/initializers/secure_headers.rb index 49ce7b42ecb..fa3255b6b25 100644 --- a/config/initializers/secure_headers.rb +++ b/config/initializers/secure_headers.rb @@ -1,5 +1,17 @@ require 'feature_management' +if FeatureManagement.rails_csp_tooling_enabled? + Rails.application.configure do + config.ssl_options = { hsts: { preload: true, expires: 1.year, subdomains: true } } + + config.action_dispatch.default_headers.merge!( + 'X-Frame-Options' => 'DENY', + 'X-XSS-Protection' => '1; mode=block', + 'X-Download-Options' => 'noopen', + ) + end +end + SecureHeaders::Configuration.default do |config| # rubocop:disable Metrics/BlockLength config.hsts = "max-age=#{365.days.to_i}; includeSubDomains; preload" config.x_frame_options = 'DENY' diff --git a/spec/requests/headers_spec.rb b/spec/requests/headers_spec.rb index 212e36558ae..ed2b8cef25d 100644 --- a/spec/requests/headers_spec.rb +++ b/spec/requests/headers_spec.rb @@ -30,4 +30,25 @@ expect(response.status).to eq 200 end + + context 'secure headers' do + it 'includes Strict-Transport-Security (HSTS)' do + get root_path, headers: { 'HTTPS' => 'on' } + + expect(response.headers['Strict-Transport-Security']). + to eq('max-age=31536000; includeSubDomains; preload') + end + + it 'sets the right values for X-headers' do + get root_path + + aggregate_failures do + expect(response.headers['X-Frame-Options']).to eq('DENY') + expect(response.headers['X-Content-Type-Options']).to eq('nosniff') + expect(response.headers['X-XSS-Protection']).to eq('1; mode=block') + expect(response.headers['X-Download-Options']).to eq('noopen') + expect(response.headers['X-Permitted-Cross-Domain-Policies']).to eq('none') + end + end + end end