diff options
author | A. Wilcox <AWilcox@Wilcox-Tech.com> | 2019-03-08 04:49:51 +0000 |
---|---|---|
committer | A. Wilcox <AWilcox@Wilcox-Tech.com> | 2019-03-08 04:49:51 +0000 |
commit | d40ddfa4cc784f8719c48c11e73a71362db76039 (patch) | |
tree | a15a54f5fb554f591bded58cfd5d3f7dcb321a33 /system/ruby/ruby-2.5.3-rubygems-v2.patch | |
parent | b6fc429feb0472552c840319844da3f14ff946bf (diff) | |
download | packages-d40ddfa4cc784f8719c48c11e73a71362db76039.tar.gz packages-d40ddfa4cc784f8719c48c11e73a71362db76039.tar.bz2 packages-d40ddfa4cc784f8719c48c11e73a71362db76039.tar.xz packages-d40ddfa4cc784f8719c48c11e73a71362db76039.zip |
system/ruby: [CVE] secbump, modernise
Diffstat (limited to 'system/ruby/ruby-2.5.3-rubygems-v2.patch')
-rw-r--r-- | system/ruby/ruby-2.5.3-rubygems-v2.patch | 408 |
1 files changed, 408 insertions, 0 deletions
diff --git a/system/ruby/ruby-2.5.3-rubygems-v2.patch b/system/ruby/ruby-2.5.3-rubygems-v2.patch new file mode 100644 index 000000000..cf2b2c7f1 --- /dev/null +++ b/system/ruby/ruby-2.5.3-rubygems-v2.patch @@ -0,0 +1,408 @@ +diff --git lib/rubygems.rb lib/rubygems.rb +index 2762bfcb88..cd7434ca87 100644 +--- a/lib/rubygems.rb ++++ b/lib/rubygems.rb +@@ -10,7 +10,7 @@ + require 'thread' + + module Gem +- VERSION = "2.7.6" ++ VERSION = "2.7.6.1" + end + + # Must be first since it unloads the prelude from 1.9.2 +diff --git lib/rubygems/command_manager.rb lib/rubygems/command_manager.rb +index 887272378e..3bee1c30a4 100644 +--- a/lib/rubygems/command_manager.rb ++++ b/lib/rubygems/command_manager.rb +@@ -7,6 +7,7 @@ + + require 'rubygems/command' + require 'rubygems/user_interaction' ++require 'rubygems/text' + + ## + # The command manager registers and installs all the individual sub-commands +@@ -32,6 +33,7 @@ + + class Gem::CommandManager + ++ include Gem::Text + include Gem::UserInteraction + + BUILTIN_COMMANDS = [ # :nodoc: +@@ -140,12 +142,12 @@ def command_names + def run(args, build_args=nil) + process_args(args, build_args) + rescue StandardError, Timeout::Error => ex +- alert_error "While executing gem ... (#{ex.class})\n #{ex}" ++ alert_error clean_text("While executing gem ... (#{ex.class})\n #{ex}") + ui.backtrace ex + + terminate_interaction(1) + rescue Interrupt +- alert_error "Interrupted" ++ alert_error clean_text("Interrupted") + terminate_interaction(1) + end + +@@ -163,7 +165,7 @@ def process_args(args, build_args=nil) + say Gem::VERSION + terminate_interaction 0 + when /^-/ then +- alert_error "Invalid option: #{args.first}. See 'gem --help'." ++ alert_error clean_text("Invalid option: #{args.first}. See 'gem --help'.") + terminate_interaction 1 + else + cmd_name = args.shift.downcase +@@ -212,7 +214,7 @@ def load_and_instantiate(command_name) + rescue Exception => e + e = load_error if load_error + +- alert_error "Loading command: #{command_name} (#{e.class})\n\t#{e}" ++ alert_error clean_text("Loading command: #{command_name} (#{e.class})\n\t#{e}") + ui.backtrace e + end + end +diff --git lib/rubygems/commands/owner_command.rb lib/rubygems/commands/owner_command.rb +index 637b5bdc4d..cac6c5a17d 100644 +--- a/lib/rubygems/commands/owner_command.rb ++++ b/lib/rubygems/commands/owner_command.rb +@@ -2,8 +2,11 @@ + require 'rubygems/command' + require 'rubygems/local_remote_options' + require 'rubygems/gemcutter_utilities' ++require 'rubygems/text' + + class Gem::Commands::OwnerCommand < Gem::Command ++ ++ include Gem::Text + include Gem::LocalRemoteOptions + include Gem::GemcutterUtilities + +@@ -64,7 +67,7 @@ def show_owners name + end + + with_response response do |resp| +- owners = Gem::SafeYAML.load resp.body ++ owners = Gem::SafeYAML.load clean_text(resp.body) + + say "Owners for gem: #{name}" + owners.each do |owner| +diff --git lib/rubygems/gemcutter_utilities.rb lib/rubygems/gemcutter_utilities.rb +index 7c6d6bb364..623d9301b5 100644 +--- a/lib/rubygems/gemcutter_utilities.rb ++++ b/lib/rubygems/gemcutter_utilities.rb +@@ -1,11 +1,14 @@ + # frozen_string_literal: true + require 'rubygems/remote_fetcher' ++require 'rubygems/text' + + ## + # Utility methods for using the RubyGems API. + + module Gem::GemcutterUtilities + ++ include Gem::Text ++ + # TODO: move to Gem::Command + OptionParser.accept Symbol do |value| + value.to_sym +@@ -145,13 +148,13 @@ def with_response response, error_prefix = nil + if block_given? then + yield response + else +- say response.body ++ say clean_text(response.body) + end + else + message = response.body + message = "#{error_prefix}: #{message}" if error_prefix + +- say message ++ say clean_text(message) + terminate_interaction 1 # TODO: question this + end + end +diff --git lib/rubygems/installer.rb lib/rubygems/installer.rb +index ee5fedeb64..904d5a0c7c 100644 +--- a/lib/rubygems/installer.rb ++++ b/lib/rubygems/installer.rb +@@ -707,9 +707,26 @@ def verify_gem_home(unpack = false) # :nodoc: + unpack or File.writable?(gem_home) + end + +- def verify_spec_name +- return if spec.name =~ Gem::Specification::VALID_NAME_PATTERN +- raise Gem::InstallError, "#{spec} has an invalid name" ++ def verify_spec ++ unless spec.name =~ Gem::Specification::VALID_NAME_PATTERN ++ raise Gem::InstallError, "#{spec} has an invalid name" ++ end ++ ++ if spec.raw_require_paths.any?{|path| path =~ /\r\n|\r|\n/ } ++ raise Gem::InstallError, "#{spec} has an invalid require_paths" ++ end ++ ++ if spec.extensions.any?{|ext| ext =~ /\r\n|\r|\n/ } ++ raise Gem::InstallError, "#{spec} has an invalid extensions" ++ end ++ ++ unless spec.specification_version.to_s =~ /\A\d+\z/ ++ raise Gem::InstallError, "#{spec} has an invalid specification_version" ++ end ++ ++ if spec.dependencies.any? {|dep| dep.type =~ /\r\n|\r|\n/ || dep.name =~ /\r\n|\r|\n/ } ++ raise Gem::InstallError, "#{spec} has an invalid dependencies" ++ end + end + + ## +@@ -836,10 +853,12 @@ def dir + def pre_install_checks + verify_gem_home options[:unpack] + ++ # The name and require_paths must be verified first, since it could contain ++ # ruby code that would be eval'ed in #ensure_loadable_spec ++ verify_spec ++ + ensure_loadable_spec + +- verify_spec_name +- + if options[:install_as_default] + Gem.ensure_default_gem_subdirectories gem_home + else +diff --git lib/rubygems/package.rb lib/rubygems/package.rb +index b924122827..b472b97a07 100644 +--- a/lib/rubygems/package.rb ++++ b/lib/rubygems/package.rb +@@ -425,6 +425,16 @@ def install_location filename, destination_dir # :nodoc: + raise Gem::Package::PathError.new(destination, destination_dir) unless + destination.start_with? destination_dir + '/' + ++ begin ++ real_destination = File.expand_path(File.realpath(destination)) ++ rescue ++ # it's fine if the destination doesn't exist, because rm -rf'ing it can't cause any damage ++ nil ++ else ++ raise Gem::Package::PathError.new(real_destination, destination_dir) unless ++ real_destination.start_with? destination_dir + '/' ++ end ++ + destination.untaint + destination + end +diff --git lib/rubygems/user_interaction.rb lib/rubygems/user_interaction.rb +index cacd782e08..eff8f9533c 100644 +--- a/lib/rubygems/user_interaction.rb ++++ b/lib/rubygems/user_interaction.rb +@@ -6,6 +6,7 @@ + #++ + + require 'rubygems/util' ++require 'rubygems/text' + + ## + # Module that defines the default UserInteraction. Any class including this +@@ -13,6 +14,8 @@ + + module Gem::DefaultUserInteraction + ++ include Gem::Text ++ + ## + # The default UI is a class variable of the singleton class for this + # module. +@@ -160,8 +163,8 @@ def terminate_interaction exit_code = 0 + # Calls +say+ with +msg+ or the results of the block if really_verbose + # is true. + +- def verbose msg = nil +- say(msg || yield) if Gem.configuration.really_verbose ++ def verbose(msg = nil) ++ say(clean_text(msg || yield)) if Gem.configuration.really_verbose + end + end + +diff --git test/rubygems/test_gem_installer.rb test/rubygems/test_gem_installer.rb +index 93b0482407..a47a307049 100644 +--- a/test/rubygems/test_gem_installer.rb ++++ b/test/rubygems/test_gem_installer.rb +@@ -1474,6 +1474,114 @@ def spec.validate; end + end + end + ++ def test_pre_install_checks_malicious_name_before_eval ++ spec = util_spec "malicious\n::Object.const_set(:FROM_EVAL, true)#", '1' ++ def spec.full_name # so the spec is buildable ++ "malicious-1" ++ end ++ def spec.validate(*args); end ++ ++ util_build_gem spec ++ ++ gem = File.join(@gemhome, 'cache', spec.file_name) ++ ++ use_ui @ui do ++ @installer = Gem::Installer.at gem ++ e = assert_raises Gem::InstallError do ++ @installer.pre_install_checks ++ end ++ assert_equal "#<Gem::Specification name=malicious\n::Object.const_set(:FROM_EVAL, true)# version=1> has an invalid name", e.message ++ end ++ refute defined?(::Object::FROM_EVAL) ++ end ++ ++ def test_pre_install_checks_malicious_require_paths_before_eval ++ spec = util_spec "malicious", '1' ++ def spec.full_name # so the spec is buildable ++ "malicious-1" ++ end ++ def spec.validate(*args); end ++ spec.require_paths = ["malicious\n``"] ++ ++ util_build_gem spec ++ ++ gem = File.join(@gemhome, 'cache', spec.file_name) ++ ++ use_ui @ui do ++ @installer = Gem::Installer.at gem ++ e = assert_raises Gem::InstallError do ++ @installer.pre_install_checks ++ end ++ assert_equal "#<Gem::Specification name=malicious version=1> has an invalid require_paths", e.message ++ end ++ end ++ ++ def test_pre_install_checks_malicious_extensions_before_eval ++ skip "mswin environment disallow to create file contained the carriage return code." if Gem.win_platform? ++ ++ spec = util_spec "malicious", '1' ++ def spec.full_name # so the spec is buildable ++ "malicious-1" ++ end ++ def spec.validate(*args); end ++ spec.extensions = ["malicious\n``"] ++ ++ util_build_gem spec ++ ++ gem = File.join(@gemhome, 'cache', spec.file_name) ++ ++ use_ui @ui do ++ @installer = Gem::Installer.at gem ++ e = assert_raises Gem::InstallError do ++ @installer.pre_install_checks ++ end ++ assert_equal "#<Gem::Specification name=malicious version=1> has an invalid extensions", e.message ++ end ++ end ++ ++ def test_pre_install_checks_malicious_specification_version_before_eval ++ spec = util_spec "malicious", '1' ++ def spec.full_name # so the spec is buildable ++ "malicious-1" ++ end ++ def spec.validate(*args); end ++ spec.specification_version = "malicious\n``" ++ ++ util_build_gem spec ++ ++ gem = File.join(@gemhome, 'cache', spec.file_name) ++ ++ use_ui @ui do ++ @installer = Gem::Installer.at gem ++ e = assert_raises Gem::InstallError do ++ @installer.pre_install_checks ++ end ++ assert_equal "#<Gem::Specification name=malicious version=1> has an invalid specification_version", e.message ++ end ++ end ++ ++ def test_pre_install_checks_malicious_dependencies_before_eval ++ spec = util_spec "malicious", '1' ++ def spec.full_name # so the spec is buildable ++ "malicious-1" ++ end ++ def spec.validate(*args); end ++ spec.add_dependency "b\nfoo", '> 5' ++ ++ util_build_gem spec ++ ++ gem = File.join(@gemhome, 'cache', spec.file_name) ++ ++ use_ui @ui do ++ @installer = Gem::Installer.at gem ++ @installer.ignore_dependencies = true ++ e = assert_raises Gem::InstallError do ++ @installer.pre_install_checks ++ end ++ assert_equal "#<Gem::Specification name=malicious version=1> has an invalid dependencies", e.message ++ end ++ end ++ + def test_shebang + util_make_exec @spec, "#!/usr/bin/ruby" + +diff --git test/rubygems/test_gem_package.rb test/rubygems/test_gem_package.rb +index d1664cf285..0b03ee2e0c 100644 +--- a/test/rubygems/test_gem_package.rb ++++ b/test/rubygems/test_gem_package.rb +@@ -480,6 +480,42 @@ def test_extract_symlink_parent + "#{destination_subdir} is not allowed", e.message) + end + ++ def test_extract_symlink_parent_doesnt_delete_user_dir ++ skip if RUBY_VERSION <= "1.8.7" ++ ++ package = Gem::Package.new @gem ++ ++ # Extract into a subdirectory of @destination; if this test fails it writes ++ # a file outside destination_subdir, but we want the file to remain inside ++ # @destination so it will be cleaned up. ++ destination_subdir = File.join @destination, 'subdir' ++ FileUtils.mkdir_p destination_subdir ++ ++ destination_user_dir = File.join @destination, 'user' ++ destination_user_subdir = File.join destination_user_dir, 'dir' ++ FileUtils.mkdir_p destination_user_subdir ++ ++ tgz_io = util_tar_gz do |tar| ++ tar.add_symlink 'link', destination_user_dir, 16877 ++ tar.add_symlink 'link/dir', '.', 16877 ++ end ++ ++ e = assert_raises(Gem::Package::PathError, Errno::EACCES) do ++ package.extract_tar_gz tgz_io, destination_subdir ++ end ++ ++ assert_path_exists destination_user_subdir ++ ++ if Gem::Package::PathError === e ++ assert_equal("installing into parent path #{destination_user_subdir} of " + ++ "#{destination_subdir} is not allowed", e.message) ++ elsif win_platform? ++ skip "symlink - must be admin with no UAC on Windows" ++ else ++ raise e ++ end ++ end ++ + def test_extract_tar_gz_directory + package = Gem::Package.new @gem + +diff --git test/rubygems/test_gem_text.rb test/rubygems/test_gem_text.rb +index 04f3f605e8..8ce6df94bb 100644 +--- a/test/rubygems/test_gem_text.rb ++++ b/test/rubygems/test_gem_text.rb +@@ -85,4 +85,9 @@ def test_truncate_text + s = "ab" * 500_001 + assert_equal "Truncating desc to 1,000,000 characters:\n#{s[0, 1_000_000]}", truncate_text(s, "desc", 1_000_000) + end ++ ++ def test_clean_text ++ assert_equal ".]2;nyan.", clean_text("\e]2;nyan\a") ++ end ++ + end |