summaryrefslogtreecommitdiff
path: root/spec/ruby/security
diff options
context:
space:
mode:
Diffstat (limited to 'spec/ruby/security')
-rw-r--r--spec/ruby/security/cve_2010_1330_spec.rb10
-rw-r--r--spec/ruby/security/cve_2011_4815_spec.rb4
-rw-r--r--spec/ruby/security/cve_2013_4164_spec.rb4
-rw-r--r--spec/ruby/security/cve_2014_8080_spec.rb32
-rw-r--r--spec/ruby/security/cve_2017_17742_spec.rb34
-rw-r--r--spec/ruby/security/cve_2018_16396_spec.rb14
-rw-r--r--spec/ruby/security/cve_2018_6914_spec.rb61
-rw-r--r--spec/ruby/security/cve_2018_8778_spec.rb6
-rw-r--r--spec/ruby/security/cve_2018_8779_spec.rb8
-rw-r--r--spec/ruby/security/cve_2018_8780_spec.rb42
-rw-r--r--spec/ruby/security/cve_2019_8321_spec.rb20
-rw-r--r--spec/ruby/security/cve_2019_8322_spec.rb24
-rw-r--r--spec/ruby/security/cve_2019_8323_spec.rb46
-rw-r--r--spec/ruby/security/cve_2019_8325_spec.rb46
-rw-r--r--spec/ruby/security/cve_2020_10663_spec.rb49
-rw-r--r--spec/ruby/security/cve_2024_49761_spec.rb7
16 files changed, 252 insertions, 155 deletions
diff --git a/spec/ruby/security/cve_2010_1330_spec.rb b/spec/ruby/security/cve_2010_1330_spec.rb
index c41a5e0a2e..8867fb7135 100644
--- a/spec/ruby/security/cve_2010_1330_spec.rb
+++ b/spec/ruby/security/cve_2010_1330_spec.rb
@@ -1,7 +1,6 @@
require_relative '../spec_helper'
describe "String#gsub" do
-
it "resists CVE-2010-1330 by raising an exception on invalid UTF-8 bytes" do
# This original vulnerability talked about KCODE, which is no longer
# used. Instead we are forcing encodings here. But I think the idea is the
@@ -9,13 +8,12 @@ describe "String#gsub" do
# #gsub on a string in the UTF-8 encoding but with invalid an UTF-8 byte
# sequence.
- str = "\xF6<script>"
- str.force_encoding Encoding::ASCII_8BIT
+ str = +"\xF6<script>"
+ str.force_encoding Encoding::BINARY
str.gsub(/</, "&lt;").should == "\xF6&lt;script>".b
str.force_encoding Encoding::UTF_8
- lambda {
+ -> {
str.gsub(/</, "&lt;")
- }.should raise_error(ArgumentError, /invalid byte sequence in UTF-8/)
+ }.should.raise(ArgumentError, /invalid byte sequence in UTF-8/)
end
-
end
diff --git a/spec/ruby/security/cve_2011_4815_spec.rb b/spec/ruby/security/cve_2011_4815_spec.rb
index 02ef10d562..554e014a1f 100644
--- a/spec/ruby/security/cve_2011_4815_spec.rb
+++ b/spec/ruby/security/cve_2011_4815_spec.rb
@@ -35,9 +35,7 @@ describe "String#hash" do
end
describe "Symbol#hash" do
- ruby_bug "#13376", "2.3.0"..."2.3.4" do
- it_behaves_like :resists_cve_2011_4815, ':a'
- end
+ it_behaves_like :resists_cve_2011_4815, ':a'
end
describe "Array#hash" do
diff --git a/spec/ruby/security/cve_2013_4164_spec.rb b/spec/ruby/security/cve_2013_4164_spec.rb
index 94578cc7ce..d223b8fd5e 100644
--- a/spec/ruby/security/cve_2013_4164_spec.rb
+++ b/spec/ruby/security/cve_2013_4164_spec.rb
@@ -3,17 +3,13 @@ require_relative '../spec_helper'
require 'json'
describe "String#to_f" do
-
it "resists CVE-2013-4164 by converting very long Strings to a Float" do
"1.#{'1'*1000000}".to_f.should be_close(1.1111111111111112, TOLERANCE)
end
-
end
describe "JSON.parse" do
-
it "resists CVE-2013-4164 by converting very long Strings to a Float" do
JSON.parse("[1.#{'1'*1000000}]").first.should be_close(1.1111111111111112, TOLERANCE)
end
-
end
diff --git a/spec/ruby/security/cve_2014_8080_spec.rb b/spec/ruby/security/cve_2014_8080_spec.rb
deleted file mode 100644
index e9d7fd320c..0000000000
--- a/spec/ruby/security/cve_2014_8080_spec.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-require_relative '../spec_helper'
-
-require 'rexml/document'
-
-describe "REXML::Document.new" do
-
- it "resists CVE-2014-8080 by raising an exception when entity expansion has grown too large" do
- xml = <<XML
- <?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE x [
- <!ENTITY % x0 "xxxxxxxxxx">
- <!ENTITY % x1 "%x0;%x0;%x0;%x0;%x0;%x0;%x0;%x0;%x0;%x0;">
- <!ENTITY % x2 "%x1;%x1;%x1;%x1;%x1;%x1;%x1;%x1;%x1;%x1;">
- <!ENTITY % x3 "%x2;%x2;%x2;%x2;%x2;%x2;%x2;%x2;%x2;%x2;">
- <!ENTITY % x4 "%x3;%x3;%x3;%x3;%x3;%x3;%x3;%x3;%x3;%x3;">
- <!ENTITY % x5 "%x4;%x4;%x4;%x4;%x4;%x4;%x4;%x4;%x4;%x4;">
- <!ENTITY % x6 "%x5;%x5;%x5;%x5;%x5;%x5;%x5;%x5;%x5;%x5;">
- <!ENTITY % x7 "%x6;%x6;%x6;%x6;%x6;%x6;%x6;%x6;%x6;%x6;">
- <!ENTITY % x8 "%x7;%x7;%x7;%x7;%x7;%x7;%x7;%x7;%x7;%x7;">
- <!ENTITY % x9 "%x8;%x8;%x8;%x8;%x8;%x8;%x8;%x8;%x8;%x8;">
- ]>
- <x>
- %x9;%x9;%x9;%x9;%x9;%x9;%x9;%x9;%x9;%x9;
- </x>
-XML
-
- lambda {
- REXML::Document.new(xml).doctype.entities['x9'].value
- }.should raise_error(REXML::ParseException, /entity expansion has grown too large/)
- end
-
-end
diff --git a/spec/ruby/security/cve_2017_17742_spec.rb b/spec/ruby/security/cve_2017_17742_spec.rb
deleted file mode 100644
index 72776cb497..0000000000
--- a/spec/ruby/security/cve_2017_17742_spec.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-require_relative '../spec_helper'
-
-require "webrick"
-require "stringio"
-require "net/http"
-
-describe "WEBrick" do
- describe "resists CVE-2017-17742" do
- it "for a response splitting headers" do
- config = WEBrick::Config::HTTP
- res = WEBrick::HTTPResponse.new config
- res['X-header'] = "malicious\r\nCookie: hack"
- io = StringIO.new
- res.send_response io
- io.rewind
- res = Net::HTTPResponse.read_new(Net::BufferedIO.new(io))
- res.code.should == '500'
- io.string.should_not =~ /hack/
- end
-
- it "for a response splitting cookie headers" do
- user_input = "malicious\r\nCookie: hack"
- config = WEBrick::Config::HTTP
- res = WEBrick::HTTPResponse.new config
- res.cookies << WEBrick::Cookie.new('author', user_input)
- io = StringIO.new
- res.send_response io
- io.rewind
- res = Net::HTTPResponse.read_new(Net::BufferedIO.new(io))
- res.code.should == '500'
- io.string.should_not =~ /hack/
- end
- end
-end
diff --git a/spec/ruby/security/cve_2018_16396_spec.rb b/spec/ruby/security/cve_2018_16396_spec.rb
index e462e0022d..6f8a5d2f5d 100644
--- a/spec/ruby/security/cve_2018_16396_spec.rb
+++ b/spec/ruby/security/cve_2018_16396_spec.rb
@@ -1,21 +1,7 @@
require_relative '../spec_helper'
describe "Array#pack" do
-
- it "resists CVE-2018-16396 by tainting output based on input" do
- "aAZBbHhuMmPp".each_char do |f|
- ["123456".taint].pack(f).tainted?.should be_true
- end
- end
-
end
describe "String#unpack" do
-
- it "resists CVE-2018-16396 by tainting output based on input" do
- "aAZBbHhuMm".each_char do |f|
- "123456".taint.unpack(f).first.tainted?.should be_true
- end
- end
-
end
diff --git a/spec/ruby/security/cve_2018_6914_spec.rb b/spec/ruby/security/cve_2018_6914_spec.rb
index a40225799d..f0aedb0dc6 100644
--- a/spec/ruby/security/cve_2018_6914_spec.rb
+++ b/spec/ruby/security/cve_2018_6914_spec.rb
@@ -1,56 +1,55 @@
require_relative '../spec_helper'
require 'tempfile'
+require 'tmpdir'
describe "CVE-2018-6914 is resisted by" do
- before :all do
- @traversal_path = Array.new(Dir.pwd.split('/').count, '..').join('/') + Dir.pwd + '/'
- @traversal_path.delete!(':') if /mswin|mingw/ =~ RUBY_PLATFORM
+ before :each do
+ @tmpdir = ENV['TMPDIR']
+ @dir = tmp("CVE-2018-6914")
+ Dir.mkdir(@dir, 0700)
+ ENV['TMPDIR'] = @dir
+ @dir << '/'
+
+ @tempfile = nil
+ end
+
+ after :each do
+ ENV['TMPDIR'] = @tmpdir
+ @tempfile.close! if @tempfile
+ rm_r @dir
end
it "Tempfile.open by deleting separators" do
- begin
- expect = Dir.glob(@traversal_path + '*').count
- t = Tempfile.open([@traversal_path, 'foo'])
- actual = Dir.glob(@traversal_path + '*').count
- actual.should == expect
- ensure
- t.close!
- end
+ @tempfile = Tempfile.open(['../', 'foo'])
+ actual = @tempfile.path
+ File.absolute_path(actual).should.start_with?(@dir)
end
it "Tempfile.new by deleting separators" do
- begin
- expect = Dir.glob(@traversal_path + '*').count
- t = Tempfile.new(@traversal_path + 'foo')
- actual = Dir.glob(@traversal_path + '*').count
- actual.should == expect
- ensure
- t.close!
- end
+ @tempfile = Tempfile.new('../foo')
+ actual = @tempfile.path
+ File.absolute_path(actual).should.start_with?(@dir)
end
it "Tempfile.create by deleting separators" do
- expect = Dir.glob(@traversal_path + '*').count
- Tempfile.create(@traversal_path + 'foo') do
- actual = Dir.glob(@traversal_path + '*').count
- actual.should == expect
+ actual = Tempfile.create('../foo') do |t|
+ t.path
end
+ File.absolute_path(actual).should.start_with?(@dir)
end
it "Dir.mktmpdir by deleting separators" do
- expect = Dir.glob(@traversal_path + '*').count
- Dir.mktmpdir(@traversal_path + 'foo') do
- actual = Dir.glob(@traversal_path + '*').count
- actual.should == expect
+ actual = Dir.mktmpdir('../foo') do |path|
+ path
end
+ File.absolute_path(actual).should.start_with?(@dir)
end
it "Dir.mktmpdir with an array by deleting separators" do
- expect = Dir.glob(@traversal_path + '*').count
- Dir.mktmpdir([@traversal_path, 'foo']) do
- actual = Dir.glob(@traversal_path + '*').count
- actual.should == expect
+ actual = Dir.mktmpdir(['../', 'foo']) do |path|
+ path
end
+ File.absolute_path(actual).should.start_with?(@dir)
end
end
diff --git a/spec/ruby/security/cve_2018_8778_spec.rb b/spec/ruby/security/cve_2018_8778_spec.rb
index a264a8581e..bbdaac734c 100644
--- a/spec/ruby/security/cve_2018_8778_spec.rb
+++ b/spec/ruby/security/cve_2018_8778_spec.rb
@@ -1,12 +1,10 @@
require_relative '../spec_helper'
describe "String#unpack" do
-
it "resists CVE-2018-8778 by raising an exception when a position indicator is larger than a native integer" do
pos = (1 << PlatformGuard::POINTER_SIZE) - 99
- lambda {
+ -> {
"0123456789".unpack("@#{pos}C10")
- }.should raise_error(RangeError, /pack length too big/)
+ }.should.raise(RangeError, /pack length too big/)
end
-
end
diff --git a/spec/ruby/security/cve_2018_8779_spec.rb b/spec/ruby/security/cve_2018_8779_spec.rb
index 9659b321ee..6d573ea7fd 100644
--- a/spec/ruby/security/cve_2018_8779_spec.rb
+++ b/spec/ruby/security/cve_2018_8779_spec.rb
@@ -16,15 +16,15 @@ platform_is_not :windows do
end
it "UNIXServer.open by raising an exception when there is a NUL byte" do
- lambda {
+ -> {
UNIXServer.open(@path+"\0")
- }.should raise_error(ArgumentError, /(path name|string) contains null byte/)
+ }.should.raise(ArgumentError, /(path name|string) contains null byte/)
end
it "UNIXSocket.open by raising an exception when there is a NUL byte" do
- lambda {
+ -> {
UNIXSocket.open(@path+"\0")
- }.should raise_error(ArgumentError, /(path name|string) contains null byte/)
+ }.should.raise(ArgumentError, /(path name|string) contains null byte/)
end
end
end
diff --git a/spec/ruby/security/cve_2018_8780_spec.rb b/spec/ruby/security/cve_2018_8780_spec.rb
index febb1de51d..dc8c6bcc9b 100644
--- a/spec/ruby/security/cve_2018_8780_spec.rb
+++ b/spec/ruby/security/cve_2018_8780_spec.rb
@@ -6,42 +6,38 @@ describe "CVE-2018-8780 is resisted by" do
end
it "Dir.glob by raising an exception when there is a NUL byte" do
- lambda {
+ -> {
Dir.glob([[@root, File.join(@root, "*")].join("\0")])
- }.should raise_error(ArgumentError, /(path name|string) contains null byte/)
+ }.should.raise(ArgumentError, /(path name|string) contains null byte/)
end
it "Dir.entries by raising an exception when there is a NUL byte" do
- lambda {
+ -> {
Dir.entries(@root+"\0")
- }.should raise_error(ArgumentError, /(path name|string) contains null byte/)
+ }.should.raise(ArgumentError, /(path name|string) contains null byte/)
end
it "Dir.foreach by raising an exception when there is a NUL byte" do
- lambda {
+ -> {
Dir.foreach(@root+"\0").to_a
- }.should raise_error(ArgumentError, /(path name|string) contains null byte/)
+ }.should.raise(ArgumentError, /(path name|string) contains null byte/)
end
- ruby_version_is "2.4" do
- it "Dir.empty? by raising an exception when there is a NUL byte" do
- lambda {
- Dir.empty?(@root+"\0")
- }.should raise_error(ArgumentError, /(path name|string) contains null byte/)
- end
+ it "Dir.empty? by raising an exception when there is a NUL byte" do
+ -> {
+ Dir.empty?(@root+"\0")
+ }.should.raise(ArgumentError, /(path name|string) contains null byte/)
end
- ruby_version_is "2.5" do
- it "Dir.children by raising an exception when there is a NUL byte" do
- lambda {
- Dir.children(@root+"\0")
- }.should raise_error(ArgumentError, /(path name|string) contains null byte/)
- end
+ it "Dir.children by raising an exception when there is a NUL byte" do
+ -> {
+ Dir.children(@root+"\0")
+ }.should.raise(ArgumentError, /(path name|string) contains null byte/)
+ end
- it "Dir.each_child by raising an exception when there is a NUL byte" do
- lambda {
- Dir.each_child(@root+"\0").to_a
- }.should raise_error(ArgumentError, /(path name|string) contains null byte/)
- end
+ it "Dir.each_child by raising an exception when there is a NUL byte" do
+ -> {
+ Dir.each_child(@root+"\0").to_a
+ }.should.raise(ArgumentError, /(path name|string) contains null byte/)
end
end
diff --git a/spec/ruby/security/cve_2019_8321_spec.rb b/spec/ruby/security/cve_2019_8321_spec.rb
new file mode 100644
index 0000000000..a8a86e7d97
--- /dev/null
+++ b/spec/ruby/security/cve_2019_8321_spec.rb
@@ -0,0 +1,20 @@
+require_relative '../spec_helper'
+
+require 'rubygems'
+require 'rubygems/user_interaction'
+
+describe "CVE-2019-8321 is resisted by" do
+ it "sanitising verbose messages" do
+ ui = Class.new {
+ include Gem::UserInteraction
+ }.new
+ ui.should_receive(:say).with(".]2;nyan.")
+ verbose_before = Gem.configuration.verbose
+ begin
+ Gem.configuration.verbose = :really_verbose
+ ui.verbose("\e]2;nyan\a")
+ ensure
+ Gem.configuration.verbose = verbose_before
+ end
+ end
+end
diff --git a/spec/ruby/security/cve_2019_8322_spec.rb b/spec/ruby/security/cve_2019_8322_spec.rb
new file mode 100644
index 0000000000..dbc273f313
--- /dev/null
+++ b/spec/ruby/security/cve_2019_8322_spec.rb
@@ -0,0 +1,24 @@
+require_relative '../spec_helper'
+
+ruby_version_is ""..."4.0" do
+
+ require 'yaml'
+ require 'rubygems'
+ require 'rubygems/safe_yaml'
+ require 'rubygems/commands/owner_command'
+
+ describe "CVE-2019-8322 is resisted by" do
+ it "sanitising owner names" do
+ command = Gem::Commands::OwnerCommand.new
+ def command.rubygems_api_request(*args)
+ Struct.new(:body).new("---\n- email: \"\e]2;nyan\a\"\n handle: handle\n id: id\n")
+ end
+ def command.with_response(response)
+ yield response
+ end
+ command.should_receive(:say).with("Owners for gem: name")
+ command.should_receive(:say).with("- .]2;nyan.")
+ command.show_owners "name"
+ end
+ end
+end
diff --git a/spec/ruby/security/cve_2019_8323_spec.rb b/spec/ruby/security/cve_2019_8323_spec.rb
new file mode 100644
index 0000000000..49a31a6682
--- /dev/null
+++ b/spec/ruby/security/cve_2019_8323_spec.rb
@@ -0,0 +1,46 @@
+require_relative '../spec_helper'
+
+require 'optparse'
+
+require 'rubygems'
+require 'rubygems/gemcutter_utilities'
+
+describe "CVE-2019-8323 is resisted by" do
+ describe "sanitising the body" do
+ it "for success codes" do
+ cutter = Class.new {
+ include Gem::GemcutterUtilities
+ }.new
+ klass = if defined?(Gem::Net::HTTPSuccess)
+ Gem::Net::HTTPSuccess
+ else
+ Net::HTTPSuccess
+ end
+ response = klass.new(nil, nil, nil)
+ def response.body
+ "\e]2;nyan\a"
+ end
+ cutter.should_receive(:say).with(".]2;nyan.")
+ cutter.with_response response
+ end
+
+ it "for error codes" do
+ cutter = Class.new {
+ include Gem::GemcutterUtilities
+ }.new
+ def cutter.terminate_interaction(n)
+ end
+ klass = if defined?(Gem::Net::HTTPNotFound)
+ Gem::Net::HTTPNotFound
+ else
+ Net::HTTPNotFound
+ end
+ response = klass.new(nil, nil, nil)
+ def response.body
+ "\e]2;nyan\a"
+ end
+ cutter.should_receive(:say).with(".]2;nyan.")
+ cutter.with_response response
+ end
+ end
+end
diff --git a/spec/ruby/security/cve_2019_8325_spec.rb b/spec/ruby/security/cve_2019_8325_spec.rb
new file mode 100644
index 0000000000..bbddb3a6ce
--- /dev/null
+++ b/spec/ruby/security/cve_2019_8325_spec.rb
@@ -0,0 +1,46 @@
+require_relative '../spec_helper'
+
+require 'rubygems'
+require 'rubygems/command_manager'
+
+describe "CVE-2019-8325 is resisted by" do
+ describe "sanitising error message components" do
+ before :each do
+ @ui = Gem::SilentUI.new
+ end
+
+ after :each do
+ @ui.close
+ end
+
+ it "for the 'while executing' message" do
+ manager = Gem::CommandManager.new
+ manager.ui = @ui
+ def manager.process_args(args, build_args)
+ raise StandardError, "\e]2;nyan\a"
+ end
+ def manager.terminate_interaction(n)
+ end
+ manager.should_receive(:alert_error).with("While executing gem ... (StandardError)\n .]2;nyan.")
+ manager.run nil, nil
+ end
+
+ it "for the 'invalid option' message" do
+ manager = Gem::CommandManager.new
+ def manager.terminate_interaction(n)
+ end
+ manager.should_receive(:alert_error).with("Invalid option: --.]2;nyan.. See 'gem --help'.")
+ manager.process_args ["--\e]2;nyan\a"], nil
+ end
+
+ it "for the 'loading command' message" do
+ manager = Gem::CommandManager.new
+ manager.ui = @ui
+ def manager.require(x)
+ raise 'foo'
+ end
+ manager.should_receive(:alert_error).with("Loading command: .]2;nyan. (RuntimeError)\n\tfoo")
+ manager.send :load_and_instantiate, "\e]2;nyan\a"
+ end
+ end
+end
diff --git a/spec/ruby/security/cve_2020_10663_spec.rb b/spec/ruby/security/cve_2020_10663_spec.rb
new file mode 100644
index 0000000000..7f42c40742
--- /dev/null
+++ b/spec/ruby/security/cve_2020_10663_spec.rb
@@ -0,0 +1,49 @@
+require_relative '../spec_helper'
+
+ruby_version_is ""..."4.0" do
+ require 'json'
+
+ module JSONSpecs
+ class MyClass
+ def initialize(foo)
+ @foo = foo
+ end
+
+ def self.json_create(hash)
+ new(*hash['args'])
+ end
+
+ def to_json(*args)
+ { 'json_class' => self.class.name, 'args' => [ @foo ] }.to_json(*args)
+ end
+ end
+ end
+
+ guard -> {
+ JSON.const_defined?(:Pure) or
+ version_is(JSON::VERSION, '2.3.0'...'2.11.0')
+ } do
+ describe "CVE-2020-10663 is resisted by" do
+ it "only creating custom objects if passed create_additions: true or using JSON.load" do
+ obj = JSONSpecs::MyClass.new("bar")
+ JSONSpecs::MyClass.should.json_creatable?
+ json = JSON.dump(obj)
+
+ JSON.parse(json, create_additions: true).class.should == JSONSpecs::MyClass
+ JSON(json, create_additions: true).class.should == JSONSpecs::MyClass
+ if version_is(JSON::VERSION, '2.8.0')
+ warning = /\Wcreate_additions:\s*true\W\s+is\s+deprecated/
+ else
+ warning = ''
+ end
+ -> {
+ JSON.load(json).class.should == JSONSpecs::MyClass
+ }.should output_to_fd(warning, STDERR)
+
+ JSON.parse(json).class.should == Hash
+ JSON.parse(json, nil).class.should == Hash
+ JSON(json).class.should == Hash
+ end
+ end
+ end
+end
diff --git a/spec/ruby/security/cve_2024_49761_spec.rb b/spec/ruby/security/cve_2024_49761_spec.rb
new file mode 100644
index 0000000000..c66b438eef
--- /dev/null
+++ b/spec/ruby/security/cve_2024_49761_spec.rb
@@ -0,0 +1,7 @@
+require_relative '../spec_helper'
+
+describe "CVE-2024-49761 is resisted by" do
+ it "the Regexp implementation handling that regular expression in linear time" do
+ Regexp.linear_time?(/&#0*((?:\d+)|(?:x[a-fA-F0-9]+));/).should == true
+ end
+end