From f5bcef3283c5213309247db1b21e2fc5a5b0624b Mon Sep 17 00:00:00 2001 From: Diego Basterrech <40240968+diebas@users.noreply.github.com> Date: Wed, 8 Jan 2025 11:33:49 -0300 Subject: [PATCH] [#162105] Handle mime type errors (#4819) * Add middleware to fix mime type errors * Refactor middleware --- config/application.rb | 2 + .../sanitize_headers_middleware.rb | 21 +++++++++++ .../sanitize_headers_middleware_spec.rb | 37 +++++++++++++++++++ 3 files changed, 60 insertions(+) create mode 100644 lib/middlewares/sanitize_headers_middleware.rb create mode 100644 spec/middlewares/sanitize_headers_middleware_spec.rb diff --git a/config/application.rb b/config/application.rb index 2308d0aab3..3be4611007 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. @@ -79,6 +80,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.active_storage.variant_processor = :vips diff --git a/lib/middlewares/sanitize_headers_middleware.rb b/lib/middlewares/sanitize_headers_middleware.rb new file mode 100644 index 0000000000..fd8fa3744c --- /dev/null +++ b/lib/middlewares/sanitize_headers_middleware.rb @@ -0,0 +1,21 @@ +class SanitizeHeadersMiddleware + def initialize(app) + @app = app + end + + def call(env) + request = ActionDispatch::Request.new(env) + + fallback_to_html_format_if_invalid_mime_type(request) + + @app.call(env) + end + + private + def fallback_to_html_format_if_invalid_mime_type(request) + request.formats + rescue ActionDispatch::Http::MimeNegotiation::InvalidType + request.set_header "CONTENT_TYPE", "text/html" + 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..0d475cc491 --- /dev/null +++ b/spec/middlewares/sanitize_headers_middleware_spec.rb @@ -0,0 +1,37 @@ +require "rack/mock" +require "rails_helper" + +RSpec.describe SanitizeHeadersMiddleware do + let(:app) { ->(env) { [200, env, "OK"] } } + let(:middleware) { described_class.new(app) } + + context "when HTTP_ACCEPT header is valid" do + it "does not alter the 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 + + context "when HTTP_ACCEPT header is invalid" do + it "sets CONTENT_TYPE to text/html" do + env = Rack::MockRequest.env_for("/", "HTTP_ACCEPT" => "../../../../../etc/passwd{{") + status, headers, _body = middleware.call(env) + + expect(env["CONTENT_TYPE"]).to eq("text/html") + expect(status).to eq(200) + end + end + + context "when HTTP_ACCEPT header is missing" do + it "does not alter the headers" do + env = Rack::MockRequest.env_for("/") + status, headers, _body = middleware.call(env) + + expect(env["CONTENT_TYPE"]).to be_nil + expect(status).to eq(200) + end + end +end