CVE-2017-0899 (published 2017-08-31T20:29Z)

RubyGems version 2.6.12 and earlier is vulnerable to maliciously crafted gem specifications that include terminal escape characters. Printing the gem specification would execute terminal escape sequences.

Severity: HIGH
CVSS v2 base score: 7.5 (AV:N/AC:L/Au:N/C:P/I:P/A:P)
CVSS v3 base score: 9.8, CRITICAL (CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-94
cwe_name: Improper Control of Generation of Code ('Code Injection')
description: The product constructs all or part of a code segment using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the syntax or behavior of the intended code segment.
extended_description: 
            When a product allows a user's input to contain code syntax, it might be possible for an attacker to craft the code in such a way that it will alter the intended control flow of the product. Such an alteration could lead to arbitrary code execution.
            Injection problems encompass a wide variety of issues -- all mitigated in very different ways. For this reason, the most effective way to discuss these weaknesses is to note the distinct features which classify them as injection weaknesses. The most important issue to note is that all injection problems share one thing in common -- i.e., they allow for the injection of control plane data into the user-controlled data plane. This means that the execution of the process may be altered by sending code in through legitimate data channels, using no other mechanism. While buffer overflows, and many other flaws, involve the use of some further issue to gain execution, injection problems need only for the data to be parsed. The most classic instantiations of this category of weakness are SQL injection and format string vulnerabilities.
         
         

Fix information:
repo_url: https://github.com/rubygems/rubygems
commit_details: repo_url: https://github.com/rubygems/rubygems
author: Evan Phoenix
author_date: 2017-05-22 09:44:08-07:00
msg: Clean any text present in gems before displaying it

This makes sure that any data pulled out of a gem spec is cleaned of all
non-printable characters before printing it. This prevents a gem from
causing havoc with a users terminal.
repository: repo_url: https://github.com/rubygems/rubygems
repo_name: rubygems/rubygems
description: Library packaging and distribution for Ruby.
repo_language: Ruby
owner: rubygems
file_changes: filename: query_command.rb
change_type: ModificationType.MODIFY
diff: @@ -226,7 +226,7 @@ def output_versions output, versions
         end
       end
 
-      output << make_entry(matching_tuples, platforms)
+      output << clean_text(make_entry(matching_tuples, platforms))
     end
   end
 

programming_language: Ruby
filename: text.rb
change_type: ModificationType.MODIFY
diff: @@ -6,13 +6,20 @@
 
 module Gem::Text
 
+  ##
+  # Remove any non-printable characters and make the text suitable for
+  # printing.
+  def clean_text(text)
+    text.gsub(/[\u0000-\u0008\u000b-\u000c\u000e-\u001F\u007f]/, ".".freeze)
+  end
+
   ##
   # Wraps +text+ to +wrap+ characters and optionally indents by +indent+
   # characters
 
   def format_text(text, wrap, indent=0)
     result = []
-    work = text.dup
+    work = clean_text(text)
 
     while work.length > wrap do
       if work =~ /^(.{0,#{wrap}})[ \n]/ then

programming_language: Ruby
filename: test_gem_commands_query_command.rb
change_type: ModificationType.MODIFY
diff: @@ -116,6 +116,46 @@ def test_execute_details
     This is a lot of text. This is a lot of text. This is a lot of text.
     This is a lot of text.
 
+pl (1)
+    Platform: i386-linux
+    Author: A User
+    Homepage: http://example.com
+
+    this is a summary
+    EOF
+
+    assert_equal expected, @ui.output
+    assert_equal '', @ui.error
+  end
+
+  def test_execute_details_cleans_text
+    spec_fetcher do |fetcher|
+      fetcher.spec 'a', 2 do |s|
+        s.summary = 'This is a lot of text. ' * 4
+        s.authors = ["Abraham Lincoln \u0001", "\u0002 Hirohito"]
+        s.homepage = "http://a.example.com/\u0003"
+      end
+
+      fetcher.legacy_platform
+    end
+
+    @cmd.handle_options %w[-r -d]
+
+    use_ui @ui do
+      @cmd.execute
+    end
+
+    expected = <<-EOF
+
+*** REMOTE GEMS ***
+
+a (2)
+    Authors: Abraham Lincoln ., . Hirohito
+    Homepage: http://a.example.com/.
+
+    This is a lot of text. This is a lot of text. This is a lot of text.
+    This is a lot of text.
+
 pl (1)
     Platform: i386-linux
     Author: A User

programming_language: Ruby
filename: test_gem_text.rb
change_type: ModificationType.MODIFY
diff: @@ -36,6 +36,10 @@ def test_format_text_trailing # for two spaces after .
     assert_equal expected, format_text(text, 78)
   end
 
+  def test_format_removes_nonprintable_characters
+    assert_equal "text with weird .. stuff", format_text("text with weird \u001b\u0002 stuff", 40)
+  end
+
   def test_min3
     assert_equal 1, min3(1, 1, 1)
     assert_equal 1, min3(1, 1, 2)

programming_language: Lua
repo_url: https://github.com/rubygems/rubygems
commit_details: repo_url: https://github.com/rubygems/rubygems
author: Samuel Giddins
author_date: 2017-08-25 17:04:08-04:00
msg: Use a pattern that works on 1.8.7
repository: repo_url: https://github.com/rubygems/rubygems
repo_name: rubygems/rubygems
description: Library packaging and distribution for Ruby.
repo_language: Ruby
owner: rubygems
file_changes: filename: text.rb
change_type: ModificationType.MODIFY
diff: @@ -10,7 +10,7 @@ module Gem::Text
   # Remove any non-printable characters and make the text suitable for
   # printing.
   def clean_text(text)
-    text.gsub(/[\u0000-\u0008\u000b-\u000c\u000e-\u001F\u007f]/, ".".freeze)
+    text.gsub(/[\000-\b\v-\f\016-\037\177]/, ".".freeze)
   end
 
   ##

programming_language: Ruby
filename: test_gem_commands_query_command.rb
change_type: ModificationType.MODIFY
diff: @@ -132,8 +132,8 @@ def test_execute_details_cleans_text
     spec_fetcher do |fetcher|
       fetcher.spec 'a', 2 do |s|
         s.summary = 'This is a lot of text. ' * 4
-        s.authors = ["Abraham Lincoln \u0001", "\u0002 Hirohito"]
-        s.homepage = "http://a.example.com/\u0003"
+        s.authors = ["Abraham Lincoln \x01", "\x02 Hirohito"]
+        s.homepage = "http://a.example.com/\x03"
       end
 
       fetcher.legacy_platform

programming_language: Ruby
filename: test_gem_text.rb
change_type: ModificationType.MODIFY
diff: @@ -37,7 +37,7 @@ def test_format_text_trailing # for two spaces after .
   end
 
   def test_format_removes_nonprintable_characters
-    assert_equal "text with weird .. stuff", format_text("text with weird \u001b\u0002 stuff", 40)
+    assert_equal "text with weird .. stuff .", format_text("text with weird \x1b\x02 stuff \x7f", 40)
   end
 
   def test_min3

programming_language: Lua