diff --git a/app/controllers/swagger_controller.rb b/app/controllers/swagger_controller.rb index af5a4b039..680bf92fc 100644 --- a/app/controllers/swagger_controller.rb +++ b/app/controllers/swagger_controller.rb @@ -1,7 +1,12 @@ class SwaggerController < ApplicationController def respond if Rails.env.development? || Rails.env.test? - render inline: Rails.root.join('swagger', derived_path).read + swagger_root = Rails.root.join('swagger') + file_path = swagger_root.join(derived_path).cleanpath + + return head :not_found unless file_path.to_s.start_with?("#{swagger_root}/") && file_path.file? + + render inline: file_path.read else head :not_found end @@ -11,8 +16,8 @@ class SwaggerController < ApplicationController def derived_path params[:path] ||= 'index.html' - path = Rack::Utils.clean_path_info(params[:path]) - path << ".#{Rack::Utils.clean_path_info(params[:format])}" unless path.ends_with?(params[:format].to_s) + path = Rack::Utils.clean_path_info(params[:path]).delete_prefix('/') + path << ".#{Rack::Utils.clean_path_info(params[:format]).delete_prefix('/')}" unless path.ends_with?(params[:format].to_s) path end end diff --git a/spec/controllers/swagger_controller_spec.rb b/spec/controllers/swagger_controller_spec.rb index f68bd6e9e..85afab318 100644 --- a/spec/controllers/swagger_controller_spec.rb +++ b/spec/controllers/swagger_controller_spec.rb @@ -8,5 +8,10 @@ describe '/swagger', type: :request do expect(response.body).to include('redoc') expect(response.body).to include('/swagger.json') end + + it 'does not render files outside the swagger directory' do + get '/swagger/%2Fetc%2Fpasswd' + expect(response).to have_http_status(:not_found) + end end end