diff options
-rw-r--r-- | Gemfile | 1 | ||||
-rw-r--r-- | Gemfile.lock | 2 | ||||
-rw-r--r-- | app/controllers/application_controller.rb | 3 | ||||
-rw-r--r-- | app/views/general/exception_caught.html.erb | 5 | ||||
-rw-r--r-- | app/views/user/_signin.html.erb | 2 | ||||
-rw-r--r-- | app/views/user/signchangeemail.html.erb | 2 | ||||
-rw-r--r-- | app/views/user/signchangepassword.html.erb | 4 | ||||
-rw-r--r-- | config/initializers/secure_headers.rb | 24 | ||||
-rw-r--r-- | spec/integration/errors_spec.rb | 3 |
9 files changed, 35 insertions, 11 deletions
@@ -25,6 +25,7 @@ gem 'recaptcha', '~> 0.3.1', :require => 'recaptcha/rails' # :require avoids "already initialized constant" warnings gem 'rmagick', :require => 'RMagick' gem 'ruby-msg', '~> 1.5.0', :git => 'git://github.com/mysociety/ruby-msg.git' +gem 'secure_headers' gem "statistics2", "~> 0.54" gem 'syslog_protocol' gem 'thin' diff --git a/Gemfile.lock b/Gemfile.lock index b5f5671f3..1ba35fdfc 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -230,6 +230,7 @@ GEM railties (~> 3.2.0) sass (>= 3.1.10) tilt (~> 1.3) + secure_headers (1.3.4) simplecov (0.7.1) multi_json (~> 1.0) simplecov-html (~> 0.7.1) @@ -330,6 +331,7 @@ DEPENDENCIES ruby-debug ruby-msg (~> 1.5.0)! sass-rails (~> 3.2.3) + secure_headers spork-rails statistics2 (~> 0.54) syslog_protocol diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 4d3f40d40..1ccf7e5db 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -17,6 +17,9 @@ class ApplicationController < ActionController::Base # assign our own handler method for non-local exceptions rescue_from Exception, :with => :render_exception + # Add some security-related headers (see config/initializers/secure_headers.rb) + ensure_security_headers + # Standard headers, footers and navigation for whole site layout "default" include FastGettext::Translation # make functions like _, n_, N_ etc available) diff --git a/app/views/general/exception_caught.html.erb b/app/views/general/exception_caught.html.erb index 8d78e2e92..21223dc1e 100644 --- a/app/views/general/exception_caught.html.erb +++ b/app/views/general/exception_caught.html.erb @@ -12,13 +12,10 @@ <%= submit_tag _("Search") %> <% end %> </li> - </ul> + </ul> <% else %> <h1><%= _("Sorry, there was a problem processing this page") %></h1> <p><%= _('You have found a bug. Please <a href="{{contact_url}}">contact us</a> to tell us about the problem', :contact_url => help_contact_path) %></p> <% end %> - <h2><%= _('Technical details') %></h2> - <p><strong><%= h(@exception_class ? @exception_class : _("Unknown")) %></strong></p> - <p><strong><%= h(@exception_message) %></strong></p> </div> diff --git a/app/views/user/_signin.html.erb b/app/views/user/_signin.html.erb index afc55d249..864951733 100644 --- a/app/views/user/_signin.html.erb +++ b/app/views/user/_signin.html.erb @@ -14,7 +14,7 @@ <p> <label class="form_label" for="user_signin_password"><%= _('Password:')%></label> - <%= password_field 'user_signin', 'password', { :size => 15, :tabindex => 20 } %> + <%= password_field 'user_signin', 'password', { :size => 15, :tabindex => 20, :autocomplete => 'off' } %> </p> <p class="form_note"> diff --git a/app/views/user/signchangeemail.html.erb b/app/views/user/signchangeemail.html.erb index 7308179f4..a99bcb785 100644 --- a/app/views/user/signchangeemail.html.erb +++ b/app/views/user/signchangeemail.html.erb @@ -23,7 +23,7 @@ <p> <label class="form_label" for="signchangeemail_password"> <%= _('Your password:')%></label> - <%= password_field 'signchangeemail', 'password', { :size => 15 } %> + <%= password_field 'signchangeemail', 'password', { :size => 15, :autocomplete => 'off' } %> </p> <p class="form_note"> diff --git a/app/views/user/signchangepassword.html.erb b/app/views/user/signchangepassword.html.erb index 51bcb466d..60f5d2c62 100644 --- a/app/views/user/signchangepassword.html.erb +++ b/app/views/user/signchangepassword.html.erb @@ -13,12 +13,12 @@ <p> <label class="form_label" for="user_password"><%= _('New password:')%></label> - <%= password_field 'user', 'password', { :size => 15 } %> + <%= password_field 'user', 'password', { :size => 15, :autocomplete => 'off' } %> </p> <p> <label class="form_label" for="user_password_confirmation"><%= _('New password: (again)')%></label> - <%= password_field 'user', 'password_confirmation', { :size => 15 } %> + <%= password_field 'user', 'password_confirmation', { :size => 15, :autocomplete => 'off' } %> </p> <div class="form_button"> diff --git a/config/initializers/secure_headers.rb b/config/initializers/secure_headers.rb new file mode 100644 index 000000000..99730e6b2 --- /dev/null +++ b/config/initializers/secure_headers.rb @@ -0,0 +1,24 @@ +::SecureHeaders::Configuration.configure do |config| + + # https://tools.ietf.org/html/rfc6797 + if AlaveteliConfiguration::force_ssl + config.hsts = { :max_age => 20.years.to_i, :include_subdomains => true } + else + config.hsts = false + end + # https://tools.ietf.org/html/draft-ietf-websec-x-frame-options-02 + config.x_frame_options = "sameorigin" + + # http://msdn.microsoft.com/en-us/library/ie/gg622941%28v=vs.85%29.aspx + config.x_content_type_options = "nosniff" + + # http://msdn.microsoft.com/en-us/library/dd565647%28v=vs.85%29.aspx + config.x_xss_protection = { :value => 1 } + + # https://w3c.github.io/webappsec/specs/content-security-policy/ + config.csp = false + + # https://www.nwebsec.com/HttpHeaders/SecurityHeaders/XDownloadOptions + config.x_download_options = false +end + diff --git a/spec/integration/errors_spec.rb b/spec/integration/errors_spec.rb index 4fa12fb21..532576bb9 100644 --- a/spec/integration/errors_spec.rb +++ b/spec/integration/errors_spec.rb @@ -59,7 +59,6 @@ describe "When errors occur" do response.should render_template('general/exception_caught') response.code.should == '404' response.body.should match("Sorry, we couldn't find that page") - response.body.should match(%Q(invalid value for Integer)) end # it 'should handle non utf-8 parameters' do @@ -76,7 +75,6 @@ describe "When errors occur" do InfoRequest.stub!(:find_by_url_title!).and_raise("An example error") get("/request/example") response.should render_template('general/exception_caught') - response.body.should match('An example error') response.code.should == "500" end @@ -111,7 +109,6 @@ describe "When errors occur" do get("/es/request/example") response.should render_template('general/exception_caught') response.body.should match('Lo sentimos, hubo un problema procesando esta página') - response.body.should match('An example error') end it "should render a 403 with text body for attempts at directory listing for attachments" do |