Fix uncaught query param encoding errors (#12741)
This commit is contained in:
		
							
								
								
									
										18
									
								
								app/middleware/handle_bad_encoding_middleware.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								app/middleware/handle_bad_encoding_middleware.rb
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | |||||||
|  | # frozen_string_literal: true | ||||||
|  | # See: https://jamescrisp.org/2018/05/28/fixing-invalid-query-parameters-invalid-encoding-in-a-rails-app/ | ||||||
|  |  | ||||||
|  | class HandleBadEncodingMiddleware | ||||||
|  |   def initialize(app) | ||||||
|  |     @app = app | ||||||
|  |   end | ||||||
|  |  | ||||||
|  |   def call(env) | ||||||
|  |     begin | ||||||
|  |       Rack::Utils.parse_nested_query(env['QUERY_STRING'].to_s) | ||||||
|  |     rescue Rack::Utils::InvalidParameterError | ||||||
|  |       env['QUERY_STRING'] = '' | ||||||
|  |     end | ||||||
|  |  | ||||||
|  |     @app.call(env) | ||||||
|  |   end | ||||||
|  | end | ||||||
| @@ -7,6 +7,7 @@ require 'rails/all' | |||||||
| Bundler.require(*Rails.groups) | Bundler.require(*Rails.groups) | ||||||
|  |  | ||||||
| require_relative '../app/lib/exceptions' | require_relative '../app/lib/exceptions' | ||||||
|  | require_relative '../app/middleware/handle_bad_encoding_middleware' | ||||||
| require_relative '../lib/paperclip/lazy_thumbnail' | require_relative '../lib/paperclip/lazy_thumbnail' | ||||||
| require_relative '../lib/paperclip/gif_transcoder' | require_relative '../lib/paperclip/gif_transcoder' | ||||||
| require_relative '../lib/paperclip/video_transcoder' | require_relative '../lib/paperclip/video_transcoder' | ||||||
| @@ -118,6 +119,7 @@ module Mastodon | |||||||
|  |  | ||||||
|     config.active_job.queue_adapter = :sidekiq |     config.active_job.queue_adapter = :sidekiq | ||||||
|  |  | ||||||
|  |     config.middleware.insert_before Rack::Runtime, HandleBadEncodingMiddleware | ||||||
|     config.middleware.use Rack::Attack |     config.middleware.use Rack::Attack | ||||||
|     config.middleware.use Rack::Deflater |     config.middleware.use Rack::Deflater | ||||||
|  |  | ||||||
|   | |||||||
| @@ -46,10 +46,7 @@ class Rack::Attack | |||||||
|  |  | ||||||
|   PROTECTED_PATHS_REGEX = Regexp.union(PROTECTED_PATHS.map { |path| /\A#{Regexp.escape(path)}/ }) |   PROTECTED_PATHS_REGEX = Regexp.union(PROTECTED_PATHS.map { |path| /\A#{Regexp.escape(path)}/ }) | ||||||
|  |  | ||||||
|   # Always allow requests from localhost |  | ||||||
|   # (blocklist & throttles are skipped) |  | ||||||
|   Rack::Attack.safelist('allow from localhost') do |req| |   Rack::Attack.safelist('allow from localhost') do |req| | ||||||
|     # Requests are allowed if the return value is truthy |  | ||||||
|     req.remote_ip == '127.0.0.1' || req.remote_ip == '::1' |     req.remote_ip == '127.0.0.1' || req.remote_ip == '::1' | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										21
									
								
								spec/middleware/handle_bad_encoding_middleware_spec.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								spec/middleware/handle_bad_encoding_middleware_spec.rb
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | |||||||
|  | require 'rails_helper' | ||||||
|  |  | ||||||
|  | RSpec.describe HandleBadEncodingMiddleware do | ||||||
|  |   let(:app) { double() } | ||||||
|  |   let(:middleware) { HandleBadEncodingMiddleware.new(app) } | ||||||
|  |  | ||||||
|  |   it "request with query string is unchanged" do | ||||||
|  |     expect(app).to receive(:call).with("PATH" => "/some/path", "QUERY_STRING" => "name=fred") | ||||||
|  |     middleware.call("PATH" => "/some/path", "QUERY_STRING" => "name=fred") | ||||||
|  |   end | ||||||
|  |  | ||||||
|  |   it "request with no query string is unchanged" do | ||||||
|  |     expect(app).to receive(:call).with("PATH" => "/some/path") | ||||||
|  |     middleware.call("PATH" => "/some/path") | ||||||
|  |   end | ||||||
|  |  | ||||||
|  |   it "request with invalid encoding in query string drops query string" do | ||||||
|  |     expect(app).to receive(:call).with("QUERY_STRING" => "", "PATH" => "/some/path") | ||||||
|  |     middleware.call("QUERY_STRING" => "q=%2Fsearch%2Fall%Forder%3Ddescending%26page%3D5%26sort%3Dcreated_at", "PATH" => "/some/path") | ||||||
|  |   end | ||||||
|  | end | ||||||
		Reference in New Issue
	
	Block a user