From f16072ec2f5d2294db3cd54bc1f49fae40349210 Mon Sep 17 00:00:00 2001 From: Keenan Brock Date: Thu, 31 Oct 2024 15:07:41 -0400 Subject: [PATCH 1/3] common image fixture files and fixture_file_upload introduce spec/fixtures with images of various image formats. Images of the name test.txt.png is a text file, but we tacked on the png suffix to ensure detection is correct. favicon.png.ico is a png, so we're using it to ensure proper detection on the server --- spec/controllers/catalog_controller_spec.rb | 6 +-- .../ops_controller/settings/upload_spec.rb | 42 +++++++----------- spec/fixtures/favicon.ico | Bin 0 -> 24838 bytes spec/fixtures/favicon.png.ico | Bin 0 -> 17863 bytes spec/fixtures/image.jpg | Bin 0 -> 4556 bytes spec/fixtures/image.png | Bin 0 -> 17863 bytes spec/fixtures/test.txt | 0 .../settings/data => fixtures}/test.txt.ico | 0 .../settings/data => fixtures}/test.txt.png | 0 9 files changed, 18 insertions(+), 30 deletions(-) create mode 100644 spec/fixtures/favicon.ico create mode 100644 spec/fixtures/favicon.png.ico create mode 100644 spec/fixtures/image.jpg create mode 100644 spec/fixtures/image.png create mode 100644 spec/fixtures/test.txt rename spec/{controllers/ops_controller/settings/data => fixtures}/test.txt.ico (100%) rename spec/{controllers/ops_controller/settings/data => fixtures}/test.txt.png (100%) diff --git a/spec/controllers/catalog_controller_spec.rb b/spec/controllers/catalog_controller_spec.rb index 3b346a25983..c3d52a6f16f 100644 --- a/spec/controllers/catalog_controller_spec.rb +++ b/spec/controllers/catalog_controller_spec.rb @@ -353,13 +353,13 @@ end it "uploads a selected png file " do - file = fixture_file_upload('files/upload_image.png', 'image/png') + file = fixture_file_upload('spec/fixtures/image.png', 'image/png') post :st_upload_image, :params => { :format => :js, :id => @st.id, :upload => {:image => file}, :active_tree => :sandt_tree, :commit => 'Upload' } - expect(assigns(:flash_array).first[:message]).to include('Custom Image file "upload_image.png" successfully uploaded') + expect(assigns(:flash_array).first[:message]).to include('Custom Image file "image.png" successfully uploaded') end it "displays an error when the selected file is not a png file or .jpg " do - file = fixture_file_upload('files/upload_image.txt', 'image/png') + file = fixture_file_upload('spec/fixtures/test.txt', 'image/png') post :st_upload_image, :params => { :format => :js, :id => @st.id, :upload => {:image => file}, :commit => 'Upload' } expect(assigns(:flash_array).first[:message]).to include("Custom Image must be a .png or .jpg file") end diff --git a/spec/controllers/ops_controller/settings/upload_spec.rb b/spec/controllers/ops_controller/settings/upload_spec.rb index a2075d59df2..692e6e11e9e 100644 --- a/spec/controllers/ops_controller/settings/upload_spec.rb +++ b/spec/controllers/ops_controller/settings/upload_spec.rb @@ -11,58 +11,49 @@ end it 'adds success flash message to @flash_array regarding updating custom logo image with a .png file' do - file = 'app/assets/images/layout/login-screen-logo.png' - controller.params = {:upload => {:logo => ActionDispatch::Http::UploadedFile.new(:tempfile => File.open(file), :filename => 'login-screen-logo.png', :type => 'image/png')}} + controller.params = {:upload => {:logo => fixture_file_upload('spec/fixtures/image.png', 'image/png')}} controller.send(:upload_logo) - expect(controller.instance_variable_get(:@flash_array)).to include(:message => 'Custom logo image "login-screen-logo.png" uploaded', :level => :success) + expect(controller.instance_variable_get(:@flash_array)).to include(:message => 'Custom logo image "image.png" uploaded', :level => :success) end it 'adds error flash message to @flash_array regarding updating custom logo image with a non-png file' do - file = File.join(__dir__, '/data/test.txt.png') - controller.params = {:upload => {:logo => ActionDispatch::Http::UploadedFile.new(:tempfile => File.open(file), :filename => 'test.txt.png', :type => 'image/png')}} + controller.params = {:upload => {:logo => fixture_file_upload('spec/fixtures/test.txt.png', 'image/png')}} controller.send(:upload_logo) expect(controller.instance_variable_get(:@flash_array)).to include(:message => 'Custom logo image must be a .png file', :level => :error) - file = 'app/assets/images/favicon.ico' - controller.params = {:upload => {:logo => ActionDispatch::Http::UploadedFile.new(:tempfile => File.open(file), :filename => 'favicon.ico', :type => 'image/png')}} + controller.params = {:upload => {:logo => fixture_file_upload('spec/fixtures/favicon.ico', 'image/png')}} controller.send(:upload_logo) expect(controller.instance_variable_get(:@flash_array)).to include(:message => 'Custom logo image must be a .png file', :level => :error) end it 'adds success flash message to @flash_array regarding updating custom login and about screen background image with a .png file' do - file = 'app/assets/images/layout/login-screen-logo.png' - controller.params = {:login => {:logo => ActionDispatch::Http::UploadedFile.new(:tempfile => File.open(file), :filename => 'login-screen-logo.png', :type => 'image/png')}} + controller.params = {:login => {:logo => fixture_file_upload('spec/fixtures/image.png', 'image/png')}} controller.send(:upload_login_logo) - expect(controller.instance_variable_get(:@flash_array)).to include(:message => 'Custom login image "login-screen-logo.png" uploaded', :level => :success) + expect(controller.instance_variable_get(:@flash_array)).to include(:message => 'Custom login image "image.png" uploaded', :level => :success) end it 'adds error flash message to @flash_array regarding updating custom login and about screen background image with a non .png file' do - file = File.join(__dir__, '/data/test.txt.png') - controller.params = {:login => {:logo => ActionDispatch::Http::UploadedFile.new(:tempfile => File.open(file), :filename => 'test.txt.png', :type => 'image/png')}} + controller.params = {:login => {:logo => fixture_file_upload('spec/fixtures/test.txt.png', 'image/png')}} controller.send(:upload_login_logo) expect(controller.instance_variable_get(:@flash_array)).to include(:message => 'Custom login image must be a .png file', :level => :error) - file = 'app/assets/images/favicon.ico' - controller.params = {:login => {:logo => ActionDispatch::Http::UploadedFile.new(:tempfile => File.open(file), :filename => 'favicon.ico', :type => 'image/png')}} + controller.params = {:login => {:logo => fixture_file_upload('spec/fixtures/favicon.ico', 'image/png')}} controller.send(:upload_login_logo) expect(controller.instance_variable_get(:@flash_array)).to include(:message => 'Custom login image must be a .png file', :level => :error) end it 'adds success flash message to @flash_array regarding updating custom brand image with a .png file' do - file = 'app/assets/images/layout/login-screen-logo.png' - controller.params = {:brand => {:logo => ActionDispatch::Http::UploadedFile.new(:tempfile => File.open(file), :filename => 'login-screen-logo.png', :type => 'image/png')}} + controller.params = {:brand => {:logo => fixture_file_upload('spec/fixtures/image.png', 'image/png')}} controller.send(:upload_login_brand) - expect(controller.instance_variable_get(:@flash_array)).to include(:message => 'Custom brand "login-screen-logo.png" uploaded', :level => :success) + expect(controller.instance_variable_get(:@flash_array)).to include(:message => 'Custom brand "image.png" uploaded', :level => :success) end it 'adds error flash message to @flash_array regarding updating custom brand image with a non .png file' do - file = File.join(__dir__, '/data/test.txt.png') - controller.params = {:brand => {:logo => ActionDispatch::Http::UploadedFile.new(:tempfile => File.open(file), :filename => 'test.txt.png', :type => 'image/png')}} + controller.params = {:brand => {:logo => fixture_file_upload('spec/fixtures/test.txt.png', 'image/png')}} controller.send(:upload_login_brand) expect(controller.instance_variable_get(:@flash_array)).to include(:message => 'Custom brand must be a .png file', :level => :error) - file = 'app/assets/images/favicon.ico' - controller.params = {:brand => {:logo => ActionDispatch::Http::UploadedFile.new(:tempfile => File.open(file), :filename => 'favicon.ico', :type => 'image/png')}} + controller.params = {:brand => {:logo => fixture_file_upload('spec/fixtures/favicon.ico', 'image/png')}} controller.send(:upload_login_brand) expect(controller.instance_variable_get(:@flash_array)).to include(:message => 'Custom brand must be a .png file', :level => :error) end @@ -76,20 +67,17 @@ end it 'adds success flash message to @flash_array regarding updating custom favicon with an .ico file' do - file = 'app/assets/images/favicon.ico' - controller.params = {:favicon => {:logo => ActionDispatch::Http::UploadedFile.new(:tempfile => File.open(file), :filename => 'favicon.ico', :type => 'image/vnd.microsoft.icon')}} + controller.params = {:favicon => {:logo => fixture_file_upload('spec/fixtures/favicon.ico', 'image/vnd.microsoft.icon')}} controller.send(:upload_favicon) expect(controller.instance_variable_get(:@flash_array)).to include(:message => 'Custom favicon "favicon.ico" uploaded', :level => :success) end it 'adds error flash message to @flash_array regarding updating custom favicon with a non .ico file' do - file = File.join(__dir__, '/data/test.txt.ico') - controller.params = {:favicon => {:logo => ActionDispatch::Http::UploadedFile.new(:tempfile => File.open(file), :filename => 'test.txt.ico', :type => 'image/png')}} + controller.params = {:favicon => {:logo => fixture_file_upload('spec/fixtures/test.txt.ico', 'image/vnd.microsoft.icon')}} controller.send(:upload_favicon) expect(controller.instance_variable_get(:@flash_array)).to include(:message => 'Custom favicon must be a .ico file', :level => :error) - file = 'app/assets/images/layout/login-screen-logo.png' - controller.params = {:favicon => {:logo => ActionDispatch::Http::UploadedFile.new(:tempfile => File.open(file), :filename => 'test.ico', :type => 'image/vnd.microsoft.icon')}} + controller.params = {:favicon => {:logo => fixture_file_upload('spec/fixtures/favicon.png.ico', 'image/vnd.microsoft.icon')}} controller.send(:upload_favicon) expect(controller.instance_variable_get(:@flash_array)).to include(:message => 'Custom favicon must be a .ico file', :level => :error) end diff --git a/spec/fixtures/favicon.ico b/spec/fixtures/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..771542ea1e679a2533234d9cde3350d354f9ead0 GIT binary patch literal 24838 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

Ves=7+#r{+(Q#2AQ$nc3(b2{j!}b*GW0Y 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 D3ZD6l literal 0 HcmV?d00001 diff --git a/spec/fixtures/image.jpg b/spec/fixtures/image.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a653fbda40fbbe74cfa2d0916f7fe156c36c79c3 GIT binary patch literal 4556 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 D3ZD6l literal 0 HcmV?d00001 diff --git a/spec/fixtures/test.txt b/spec/fixtures/test.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/spec/controllers/ops_controller/settings/data/test.txt.ico b/spec/fixtures/test.txt.ico similarity index 100% rename from spec/controllers/ops_controller/settings/data/test.txt.ico rename to spec/fixtures/test.txt.ico diff --git a/spec/controllers/ops_controller/settings/data/test.txt.png b/spec/fixtures/test.txt.png similarity index 100% rename from spec/controllers/ops_controller/settings/data/test.txt.png rename to spec/fixtures/test.txt.png From ce85853e5dd2eff2091be2210c2c1bebfe80e540 Mon Sep 17 00:00:00 2001 From: Keenan Brock Date: Tue, 29 Oct 2024 15:15:12 -0400 Subject: [PATCH 2/3] Ensure catalog uploaded images are image files Consolidated catalog uploads and icon uploads. Checking image magic numbers to ensure it is a png or jpg Resolves issue where user could upload a zip bomb --- app/controllers/catalog_controller.rb | 3 +- .../mixins/image_validation_mixin.rb | 32 +++++++++++++++++++ .../ops_controller/settings/upload.rb | 27 ++-------------- spec/controllers/catalog_controller_spec.rb | 8 ++++- 4 files changed, 43 insertions(+), 27 deletions(-) create mode 100644 app/controllers/mixins/image_validation_mixin.rb diff --git a/app/controllers/catalog_controller.rb b/app/controllers/catalog_controller.rb index 6540d534df1..59aabdb56b7 100644 --- a/app/controllers/catalog_controller.rb +++ b/app/controllers/catalog_controller.rb @@ -3,6 +3,7 @@ class CatalogController < ApplicationController include Mixins::ServiceDialogCreationMixin include Mixins::BreadcrumbsMixin include Mixins::AutomationMixin + include Mixins::ImageValidationMixin before_action :check_privileges before_action :get_session_data @@ -540,7 +541,7 @@ def st_upload_image elsif params[:upload] && params[:upload][:image] && params[:upload][:image].respond_to?(:read) ext = params[:upload][:image].original_filename.split(".").last.downcase - if !%w[png jpg].include?(ext) + if !valid_image_file?(params[:upload][:image]) msg = _("Custom Image must be a .png or .jpg file") err = true else diff --git a/app/controllers/mixins/image_validation_mixin.rb b/app/controllers/mixins/image_validation_mixin.rb new file mode 100644 index 00000000000..0c81f0d4af8 --- /dev/null +++ b/app/controllers/mixins/image_validation_mixin.rb @@ -0,0 +1,32 @@ +module Mixins + module ImageValidationMixin + private + + # @param file request parameter for a file + # @param ext if present, the only extension supported (default: nil / accept all extensions) + def valid_image_file?(file, type = nil) + ext = file.original_filename.split(".").last.downcase + return false if type && !Array.wrap(type).include?(ext) + + valid_magic_number = + case ext + when "ico" + "\x00\x00\x01\x00".force_encoding("ASCII-8BIT") + when "png" + "\x89PNG\r\n\x1A\n".force_encoding("ASCII-8BIT") + when "jpg" + "\xff\xd8\xff".force_encoding("ASCII-8BIT") + else + return false + end + + magic_number = File.open(file.tempfile.path, 'rb') do |f| + f.readpartial(valid_magic_number.size) + end + + magic_number == valid_magic_number + rescue EOFError + return false + end + end +end diff --git a/app/controllers/ops_controller/settings/upload.rb b/app/controllers/ops_controller/settings/upload.rb index 8671fe609cf..1be5a7c969e 100644 --- a/app/controllers/ops_controller/settings/upload.rb +++ b/app/controllers/ops_controller/settings/upload.rb @@ -1,5 +1,6 @@ module OpsController::Settings::Upload extend ActiveSupport::Concern + include Mixins::ImageValidationMixin def upload_logo assert_privileges("ops_settings") @@ -31,7 +32,7 @@ def upload_favicon def upload_logos(file, field, text, type) if field && field[:logo] && field[:logo].respond_to?(:read) - unless valid_file?(field[:logo], type) + unless valid_image_file?(field[:logo], type) add_flash(_("%{image} must be a .%{type} file") % {:image => text, :type => type}, :error) else File.open(file, "wb") { |f| f.write(field[:logo].read) } @@ -115,28 +116,4 @@ def logo_dir Dir.mkdir(dir) unless dir.exist? dir.to_s end - - def valid_file?(file, type) - ext = file.original_filename.split(".").last.downcase - return false unless ext == type - - case type - when "ico" - valid_magic_number = "\x00\x00\x01\x00".force_encoding("ASCII-8BIT") - when "png" - valid_magic_number = "\x89PNG\r\n\x1A\n".force_encoding("ASCII-8BIT") - else - return false - end - - magic_number = File.open(file.tempfile.path, 'rb') do |f| - begin - f.readpartial(valid_magic_number.size) - rescue EOFError - return false - end - end - - magic_number == valid_magic_number - end end diff --git a/spec/controllers/catalog_controller_spec.rb b/spec/controllers/catalog_controller_spec.rb index c3d52a6f16f..c5c249e699d 100644 --- a/spec/controllers/catalog_controller_spec.rb +++ b/spec/controllers/catalog_controller_spec.rb @@ -358,8 +358,14 @@ expect(assigns(:flash_array).first[:message]).to include('Custom Image file "image.png" successfully uploaded') end + it "uploads a selected jpg file " do + file = fixture_file_upload('spec/fixtures/image.jpg', 'image/jpeg') + post :st_upload_image, :params => { :format => :js, :id => @st.id, :upload => {:image => file}, :active_tree => :sandt_tree, :commit => 'Upload' } + expect(assigns(:flash_array).first[:message]).to include('Custom Image file "image.jpg" successfully uploaded') + end + it "displays an error when the selected file is not a png file or .jpg " do - file = fixture_file_upload('spec/fixtures/test.txt', 'image/png') + file = fixture_file_upload('spec/fixtures/test.txt.png', 'image/png') post :st_upload_image, :params => { :format => :js, :id => @st.id, :upload => {:image => file}, :commit => 'Upload' } expect(assigns(:flash_array).first[:message]).to include("Custom Image must be a .png or .jpg file") end From 6463af5996542981e6281e125c8008eba9e8f8a6 Mon Sep 17 00:00:00 2001 From: Keenan Brock Date: Fri, 25 Oct 2024 16:02:27 -0400 Subject: [PATCH 3/3] flatten ifs in catalog_controller image processing --- app/controllers/catalog_controller.rb | 35 ++++++++++++--------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/app/controllers/catalog_controller.rb b/app/controllers/catalog_controller.rb index 59aabdb56b7..3808add3528 100644 --- a/app/controllers/catalog_controller.rb +++ b/app/controllers/catalog_controller.rb @@ -534,31 +534,28 @@ def st_upload_image err = false identify_catalog(params[:id]) + image_file = params.dig(:upload, :image) if params[:pressed] @record.picture = nil @record.save msg = _("Custom Image successfully removed") - elsif params[:upload] && params[:upload][:image] && - params[:upload][:image].respond_to?(:read) - ext = params[:upload][:image].original_filename.split(".").last.downcase - if !valid_image_file?(params[:upload][:image]) - msg = _("Custom Image must be a .png or .jpg file") - err = true - else - picture = {:content => params[:upload][:image].read, - :extension => ext} - if @record.picture.nil? - @record.picture = Picture.new(picture) - else - @record.picture.update(picture) - end - @record.save - msg = _("Custom Image file \"%{name}\" successfully uploaded") % - {:name => params[:upload][:image].original_filename} - end - else + elsif !image_file&.respond_to?(:read) msg = _("Use the Choose file button to locate a .png or .jpg image file") err = true + elsif !valid_image_file?(image_file) + msg = _("Custom Image must be a .png or .jpg file") + err = true + else + ext = image_file.original_filename.split(".").last.downcase + picture = {:content => image_file.read, :extension => ext} + if @record.picture.nil? + @record.picture = Picture.new(picture) + else + @record.picture.update(picture) + end + @record.save + msg = _("Custom Image file \"%{name}\" successfully uploaded") % + {:name => image_file.original_filename} end params[:id] = x_build_node_id(@record) # Get the tree node id add_flash(msg, err == true ? :error : nil)