diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index a492bcd50a..eac9635bd1 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -193,6 +193,7 @@ def formats_with_html_fallback end def render_403(_exception) + byebug if current_user render "errors/forbidden", status: 403, layout: "application", formats: formats_with_html_fallback else diff --git a/config/application.rb b/config/application.rb index f71f33b27a..07d24f26cb 100644 --- a/config/application.rb +++ b/config/application.rb @@ -5,6 +5,7 @@ require "rails/all" require "will_paginate/array" require "active_storage/engine" +require_relative "../lib/middlewares/sanitize_headers_middleware" # Require the gems listed in Gemfile, including any gems # you've limited to :test, :development, or :production. @@ -54,6 +55,9 @@ class Application < Rails::Application # config.autoload_paths += Dir["#{config.root}/lib"] # config.eager_load_paths += Dir["#{config.root}/lib"] + config.autoload_paths << Rails.root.join("lib/middlewares") + config.eager_load_paths << Rails.root.join("lib/middlewares") + config.autoload_paths += Dir["#{config.root}/app/models/external_services"] config.eager_load_paths += Dir["#{config.root}/app/models/external_services"] @@ -79,6 +83,7 @@ class Application < Rails::Application # Prevent invalid (usually malicious) URLs from causing exceptions/issues config.middleware.insert 0, Rack::UTF8Sanitizer + config.middleware.insert_before Rack::UTF8Sanitizer, SanitizeHeadersMiddleware config.exceptions_app = self.routes diff --git a/lib/middlewares/sanitize_headers_middleware.rb b/lib/middlewares/sanitize_headers_middleware.rb new file mode 100644 index 0000000000..fceae1c5b5 --- /dev/null +++ b/lib/middlewares/sanitize_headers_middleware.rb @@ -0,0 +1,11 @@ +class SanitizeHeadersMiddleware + def initialize(app) + @app = app + end + + def call(env) + env["HTTP_ACCEPT"] = "*/*" if env["HTTP_ACCEPT"] =~ /(\.\.|{|})/ + + @app.call(env) + end +end diff --git a/spec/middlewares/sanitize_headers_middleware_spec.rb b/spec/middlewares/sanitize_headers_middleware_spec.rb new file mode 100644 index 0000000000..700f424d9b --- /dev/null +++ b/spec/middlewares/sanitize_headers_middleware_spec.rb @@ -0,0 +1,21 @@ +require "rack/mock" +require "rails_helper" + +RSpec.describe SanitizeHeadersMiddleware do + let(:app) { ->(env) { [200, env, "OK"] } } + let(:middleware) { described_class.new(app) } + + it "sanitizes invalid HTTP_ACCEPT headers" do + env = Rack::MockRequest.env_for("/", "HTTP_ACCEPT" => "../../../../../etc/passwd{{") + status, headers, _body = middleware.call(env) + expect(env["HTTP_ACCEPT"]).to eq("*/*") + expect(status).to eq(200) + end + + it "allows valid HTTP_ACCEPT headers" do + env = Rack::MockRequest.env_for("/", "HTTP_ACCEPT" => "text/html,application/json") + status, headers, _body = middleware.call(env) + expect(env["HTTP_ACCEPT"]).to eq("text/html,application/json") + expect(status).to eq(200) + end +end