CVE-2017-0901: Improper Input Validation (CWE-20)
value: RubyGems version 2.6.12 and earlier fails to validate specification names, allowing a maliciously crafted gem to potentially overwrite any file on the filesystem.
CWE description: The product receives input or data, but it does
        not validate or incorrectly validates that the input has the
        properties that are required to process the data safely and
        correctly.
CVSS v3 base score: 7.5
Published: 2017-08-31T20:29Z
Repository: https://github.com/rubygems/rubygems
Language: Ruby
Files changed: lib/rubygems/installer.rb, test/rubygems/test_gem_installer.rb
Commit date: 2017-08-27 20:37:15 -0500
Commit message: Validate specification names when installing

This prevents a malicious user from crafting a gem that could write to an arbitrary directory, outside of the gems directory, by using metacharacters such as `..`

Diff: diff --git a/lib/rubygems/installer.rb b/lib/rubygems/installer.rb
index 967543c2d..6fd3399dd 100644
--- a/lib/rubygems/installer.rb
+++ b/lib/rubygems/installer.rb
@@ -695,10 +695,15 @@ def verify_gem_home(unpack = false) # :nodoc:
     FileUtils.mkdir_p gem_home
     raise Gem::FilePermissionError, gem_home unless
       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"
+  end
+
   ##
   # Return the text for an application file.
 
   def app_script_text(bin_file_name)
     # note that the `load` lines cannot be indented, as old RG versions match
@@ -821,10 +826,12 @@ def dir
   def pre_install_checks
     verify_gem_home options[:unpack]
 
     ensure_loadable_spec
 
+    verify_spec_name
+
     if options[:install_as_default]
       Gem.ensure_default_gem_subdirectories gem_home
     else
       Gem.ensure_gem_subdirectories gem_home
     end
diff --git a/test/rubygems/test_gem_installer.rb b/test/rubygems/test_gem_installer.rb
index 882981d34..dd049214f 100644
--- a/test/rubygems/test_gem_installer.rb
+++ b/test/rubygems/test_gem_installer.rb
@@ -1446,10 +1446,30 @@ def test_pre_install_checks_wrong_rubygems_version
       assert_equal 'old_rubygems_required requires RubyGems version < 0. ' +
         "Try 'gem update --system' to update RubyGems itself.", e.message
     end
   end
 
+  def test_pre_install_checks_malicious_name
+    spec = util_spec '../malicious', '1'
+    def spec.full_name # so the spec is buildable
+      "malicious-1"
+    end
+    def spec.validate; 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 version=1> has an invalid name', e.message
+    end
+  end
+
   def test_shebang
     util_make_exec @spec, "#!/usr/bin/ruby"
 
     shebang = @installer.shebang 'executable'
 

Fixed code:   def verify_spec_name
    return if spec.name =~ Gem::Specification::VALID_NAME_PATTERN
    raise Gem::InstallError, "#{spec} has an invalid name"
  end

    verify_spec_name

  def test_pre_install_checks_malicious_name
    spec = util_spec '../malicious', '1'
    def spec.full_name # so the spec is buildable
      "malicious-1"
    end
    def spec.validate; 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 version=1> has an invalid name', e.message
    end
  end