Package: release.debian.org
User: release.debian....@packages.debian.org
X-Debbugs-Cc: debian-r...@lists.debian.org
Usertags: pu
Tags: buster
Severity: normal

Hello,

ruby-mechanize was affected by CVE-2021-21289, where the package was
vulnerable to command injection vulnerability.

This has been fixed in sid, bullseye, and stretch.
Here's the debdiff for buster-pu:

8<------8<------8<------8<------8<------8<------8<------8<------8<------8<

diff -Nru ruby-mechanize-2.7.6/debian/changelog
ruby-mechanize-2.7.6/debian/changelog
--- ruby-mechanize-2.7.6/debian/changelog    2019-01-04 16:57:45.000000000 +0530
+++ ruby-mechanize-2.7.6/debian/changelog    2021-02-19 22:47:27.000000000 +0530
@@ -1,3 +1,10 @@
+ruby-mechanize (2.7.6-1+deb10u1) buster; urgency=medium
+
+  * Team upload for buster-pu.
+  * Add patch to prevent OS command injection. (Fixes: CVE-2021-21289)
+
+ -- Utkarsh Gupta <utka...@debian.org>  Fri, 19 Feb 2021 22:47:27 +0530
+
 ruby-mechanize (2.7.6-1) unstable; urgency=medium

   * Team upload
diff -Nru ruby-mechanize-2.7.6/debian/patches/CVE-2021-21289.patch
ruby-mechanize-2.7.6/debian/patches/CVE-2021-21289.patch
--- ruby-mechanize-2.7.6/debian/patches/CVE-2021-21289.patch
1970-01-01 05:30:00.000000000 +0530
+++ ruby-mechanize-2.7.6/debian/patches/CVE-2021-21289.patch
2021-02-19 22:46:52.000000000 +0530
@@ -0,0 +1,260 @@
+From aae0b13514a1a0caf93b1cf233733c50e679069a Mon Sep 17 00:00:00 2001
+From: Katsuhiko YOSHIDA <clad...@gmail.com>
+Date: Sat, 20 Jul 2019 11:03:40 +0900
+Subject: [PATCH 1/7] fix(security): prevent command injection in CookieJar
+
+Related to 
https://github.com/sparklemotion/mechanize/security/advisories/GHSA-qrqm-fpv6-6r8g
+---
+ lib/mechanize/cookie_jar.rb       |  4 ++--
+ test/test_mechanize_cookie_jar.rb | 30 ++++++++++++++++++++++++++++++
+ 2 files changed, 32 insertions(+), 2 deletions(-)
+
+--- a/lib/mechanize/cookie_jar.rb
++++ b/lib/mechanize/cookie_jar.rb
+@@ -65,7 +65,7 @@
+   class CookieJar < ::HTTP::CookieJar
+     def save(output, *options)
+       output.respond_to?(:write) or
+-        return open(output, 'w') { |io| save(io, *options) }
++        return ::File.open(output, 'w') { |io| save(io, *options) }
+
+       opthash = {
+         :format => :yaml,
+@@ -119,7 +119,7 @@
+
+     def load(input, *options)
+       input.respond_to?(:write) or
+-        return open(input, 'r') { |io| load(io, *options) }
++        return ::File.open(input, 'r') { |io| load(io, *options) }
+
+       opthash = {
+         :format => :yaml,
+--- a/test/test_mechanize_cookie_jar.rb
++++ b/test/test_mechanize_cookie_jar.rb
+@@ -1,4 +1,5 @@
+ require 'mechanize/test_case'
++require 'fileutils'
+
+ class TestMechanizeCookieJar < Mechanize::TestCase
+
+@@ -500,6 +501,35 @@
+     assert_equal(0, @jar.cookies(url).length)
+   end
+
++  def test_prevent_command_injection_when_saving
++    url = URI 'http://rubygems.org/'
++    path = '| ruby -rfileutils -e \'FileUtils.touch("vul.txt")\''
++
++    @jar.add(url, Mechanize::Cookie.new(cookie_values))
++
++    in_tmpdir do
++      @jar.save_as(path, :cookiestxt)
++      assert_equal(false, File.exist?('vul.txt'))
++    end
++  end
++
++  def test_prevent_command_injection_when_loading
++    url = URI 'http://rubygems.org/'
++    path = '| ruby -rfileutils -e \'FileUtils.touch("vul.txt")\''
++
++    @jar.add(url, Mechanize::Cookie.new(cookie_values))
++
++    in_tmpdir do
++      @jar.save_as("cookies.txt", :cookiestxt)
++      @jar.clear!
++
++      assert_raises Errno::ENOENT do
++        @jar.load(path, :cookiestxt)
++      end
++      assert_equal(false, File.exist?('vul.txt'))
++    end
++  end
++
+   def test_save_and_read_expired_cookies
+     url = URI 'http://rubyforge.org/'
+
+--- a/lib/mechanize.rb
++++ b/lib/mechanize.rb
+@@ -396,7 +396,7 @@
+     io = if io_or_filename.respond_to? :write then
+            io_or_filename
+          else
+-           open io_or_filename, 'wb'
++           ::File.open(io_or_filename, 'wb')
+          end
+
+     case page
+--- a/test/test_mechanize.rb
++++ b/test/test_mechanize.rb
+@@ -345,6 +345,14 @@
+     end
+   end
+
++  def test_download_does_not_allow_command_injection
++    in_tmpdir do
++      @mech.download('http://example', '| ruby -rfileutils -e
\'FileUtils.touch("vul.txt")\'')
++
++      refute_operator(File, :exist?, "vul.txt")
++    end
++  end
++
+   def test_get
+     uri = URI 'http://localhost'
+
+--- a/lib/mechanize/download.rb
++++ b/lib/mechanize/download.rb
+@@ -71,7 +71,7 @@
+     dirname = File.dirname filename
+     FileUtils.mkdir_p dirname
+
+-    open filename, 'wb' do |io|
++    ::File.open(filename, 'wb')do |io|
+       until @body_io.eof? do
+         io.write @body_io.read 16384
+       end
+--- a/test/test_mechanize_download.rb
++++ b/test/test_mechanize_download.rb
+@@ -46,6 +46,18 @@
+     end
+   end
+
++  def test_save_bang_does_not_allow_command_injection
++    uri = URI.parse 'http://example/foo.html'
++    body_io = StringIO.new '0123456789'
++
++    download = @parser.new uri, nil, body_io
++
++    in_tmpdir do
++      download.save!('| ruby -rfileutils -e \'FileUtils.touch("vul.txt")\'')
++      refute_operator(File, :exist?, "vul.txt")
++    end
++  end
++
+   def test_save_tempfile
+     uri = URI.parse 'http://example/foo.html'
+     Tempfile.open @NAME do |body_io|
+@@ -84,6 +96,5 @@
+
+     assert_equal "foo.html", download.filename
+   end
+-
+ end
+
+--- a/lib/mechanize/file.rb
++++ b/lib/mechanize/file.rb
+@@ -82,7 +82,7 @@
+     dirname = File.dirname filename
+     FileUtils.mkdir_p dirname
+
+-    open filename, 'wb' do |f|
++    ::File.open(filename, 'wb')do |f|
+       f.write body
+     end
+
+--- a/test/test_mechanize_file.rb
++++ b/test/test_mechanize_file.rb
+@@ -103,5 +103,14 @@
+     end
+   end
+
++  def test_save_bang_does_not_allow_command_injection
++    uri = URI 'http://example/test.html'
++    page = Mechanize::File.new uri, nil, ''
++
++    in_tmpdir do
++      page.save!('| ruby -rfileutils -e \'FileUtils.touch("vul.txt")\'')
++      refute_operator(File, :exist?, "vul.txt")
++    end
++  end
+ end
+
+--- a/lib/mechanize/file_response.rb
++++ b/lib/mechanize/file_response.rb
+@@ -15,7 +15,7 @@
+     if directory?
+       yield dir_body
+     else
+-      open @file_path, 'rb' do |io|
++      ::File.open(@file_path, 'rb') do |io|
+         yield io.read
+       end
+     end
+--- a/test/test_mechanize_file_response.rb
++++ b/test/test_mechanize_file_response.rb
+@@ -1,7 +1,6 @@
+ require 'mechanize/test_case'
+
+ class TestMechanizeFileResponse < Mechanize::TestCase
+-
+   def test_content_type
+     Tempfile.open %w[pi .nothtml] do |tempfile|
+       res = Mechanize::FileResponse.new tempfile.path
+@@ -19,5 +18,24 @@
+     end
+   end
+
+-end
++  def test_read_body
++    Tempfile.open %w[pi .html] do |tempfile|
++      tempfile.write("asdfasdfasdf")
++      tempfile.close
+
++      res = Mechanize::FileResponse.new(tempfile.path)
++      res.read_body do |input|
++        assert_equal("asdfasdfasdf", input)
++      end
++    end
++  end
++
++  def test_read_body_does_not_allow_command_injection
++    in_tmpdir do
++      FileUtils.touch('| ruby -rfileutils -e \'FileUtils.touch("vul.txt")\'')
++      res = Mechanize::FileResponse.new('| ruby -rfileutils -e
\'FileUtils.touch("vul.txt")\'')
++      res.read_body { |_| }
++      refute_operator(File, :exist?, "vul.txt")
++    end
++  end
++end
+--- a/lib/mechanize/test_case.rb
++++ b/lib/mechanize/test_case.rb
+@@ -235,9 +235,9 @@
+     else
+       filename = "htdocs#{path.gsub(/[^\/\\.\w\s]/, '_')}"
+       unless PAGE_CACHE[filename]
+-        open("#{Mechanize::TestCase::TEST_DIR}/#{filename}", 'rb') { |io|
++        ::File.open("#{Mechanize::TestCase::TEST_DIR}/#{filename}",
'rb') do |io|
+           PAGE_CACHE[filename] = io.read
+-        }
++        end
+       end
+
+       res.body = PAGE_CACHE[filename]
+--- a/lib/mechanize/test_case/gzip_servlet.rb
++++ b/lib/mechanize/test_case/gzip_servlet.rb
+@@ -15,7 +15,7 @@
+     end
+
+     if name = req.query['file'] then
+-      open "#{TEST_DIR}/htdocs/#{name}" do |io|
++      ::File.open("#{TEST_DIR}/htdocs/#{name}") do |io|
+         string = ""
+         zipped = StringIO.new string, 'w'
+         Zlib::GzipWriter.wrap zipped do |gz|
+--- a/lib/mechanize/test_case/verb_servlet.rb
++++ b/lib/mechanize/test_case/verb_servlet.rb
+@@ -1,11 +1,9 @@
+ class VerbServlet < WEBrick::HTTPServlet::AbstractServlet
+   %w[HEAD GET POST PUT DELETE].each do |verb|
+-    eval <<-METHOD
+-      def do_#{verb}(req, res)
+-        res.header['X-Request-Method'] = #{verb.dump}
+-        res.body = #{verb.dump}
+-      end
+-    METHOD
++    define_method "do_#{verb}" do |req, res|
++      res.header['X-Request-Method'] = verb
++      res.body = verb
++    end
+   end
+ end
+
diff -Nru ruby-mechanize-2.7.6/debian/patches/series
ruby-mechanize-2.7.6/debian/patches/series
--- ruby-mechanize-2.7.6/debian/patches/series    2019-01-04
16:57:45.000000000 +0530
+++ ruby-mechanize-2.7.6/debian/patches/series    2021-02-19
22:46:49.000000000 +0530
@@ -1,3 +1,4 @@
 dont_require_rubygems
 set_path_for_test
 0003-Replace-dep-on-ntlm-http-by-rubyntlm.patch
+CVE-2021-21289.patch

8<------8<------8<------8<------8<------8<------8<------8<------8<------8<


- u

Reply via email to