diff --git a/config/application.rb b/config/application.rb index b851ce627c5..5dc78745da3 100644 --- a/config/application.rb +++ b/config/application.rb @@ -33,7 +33,8 @@ class Application < Rails::Application event.payload.except(:params, :headers) end - config.middleware.insert_before 0, Rack::HeadersFilter + require 'headers_filter' + config.middleware.insert_before 0, HeadersFilter config.middleware.insert_before 0, Rack::Cors do allow do diff --git a/lib/headers_filter.rb b/lib/headers_filter.rb new file mode 100644 index 00000000000..44e7cbd610d --- /dev/null +++ b/lib/headers_filter.rb @@ -0,0 +1,21 @@ +require 'rack/headers_filter' + +# Expands on Rack::HeadersFilter to delete additional headers +class HeadersFilter + HEADERS_TO_DELETE = Rack::HeadersFilter::SENSITIVE_HEADERS + %w[ + HTTP_HOST + ] + + def initialize(app) + @app = app + end + + def call(env) + HEADERS_TO_DELETE.each { |header| env.delete(header) } + app.call(env) + end + + private + + attr_reader :app +end diff --git a/spec/lib/headers_filter_spec.rb b/spec/lib/headers_filter_spec.rb new file mode 100644 index 00000000000..7f83e12cc1a --- /dev/null +++ b/spec/lib/headers_filter_spec.rb @@ -0,0 +1,21 @@ +require 'rails_helper' + +RSpec.describe HeadersFilter do + let(:app) { double('App', call: nil) } + + let(:middleware) { HeadersFilter.new(app) } + + describe '#call' do + it 'removes untrusted headers from the env' do + env = { + 'HTTP_HOST' => 'foobar.com', + 'HTTP_X_FORWARDED_HOST' => 'evil.com', + } + + middleware.call(env) + + expect(env).to_not have_key('HTTP_HOST') + expect(env).to_not have_key('HTTP_X_FORWARDED_HOST') + end + end +end diff --git a/spec/requests/headers_spec.rb b/spec/requests/headers_spec.rb index 70d91a9d9f5..f74fb8cb603 100644 --- a/spec/requests/headers_spec.rb +++ b/spec/requests/headers_spec.rb @@ -6,4 +6,10 @@ expect(response.body).to_not include('evil.com') end + + it 'does not blow up with a malicious host value' do + get root_path, headers: { 'Host' => "mTpvPME6'));select pg_sleep(9); --" } + + expect(response.code.to_i).to eq(200) + end end