Bug#983113: buster-pu: package ruby-mechanize/2.7.6-1+deb10u1
Package: release.debian.org
User: release.debian.org@packages.debian.org
X-Debbugs-Cc: debian-ruby@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 <utkarsh@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 <claddvd@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 to: