rubygems-update 2.7.5 → 2.7.6
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rubygems-update might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/History.txt +19 -0
- data/lib/rubygems.rb +1 -1
- data/lib/rubygems/commands/owner_command.rb +1 -1
- data/lib/rubygems/package.rb +33 -4
- data/lib/rubygems/package/tar_header.rb +14 -9
- data/lib/rubygems/package/tar_writer.rb +2 -0
- data/lib/rubygems/server.rb +13 -1
- data/lib/rubygems/specification.rb +11 -4
- data/test/rubygems/test_gem_commands_owner_command.rb +25 -0
- data/test/rubygems/test_gem_package.rb +73 -1
- data/test/rubygems/test_gem_package_tar_header.rb +20 -0
- data/test/rubygems/test_gem_server.rb +165 -0
- data/test/rubygems/test_gem_specification.rb +16 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0fa366bda5b1ed46730b8c276ce161ef32966ec9dde14f974663508163df41da
|
4
|
+
data.tar.gz: 76d8c2583652ec7266303e5af81014b7b6c440ff207e1d4cbe483959226db55d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cd712f404f5e736191c312af58dafdfe897e155b9cdec68a634547606846bb31bae7cdefc46ace35eb143db7f8281c20092a534a7ccb94760ad5701d8c0ca06f
|
7
|
+
data.tar.gz: 1d80df8990549a07c91d94c5e848141f72045a71046ef0a3be5b871e8af9f0909187b196d117b6c508ec9fd0c9238a0ed96e4f9a8c7f6a9f6b59feac8a7df25b
|
data/History.txt
CHANGED
@@ -1,5 +1,24 @@
|
|
1
1
|
# coding: UTF-8
|
2
2
|
|
3
|
+
=== 2.7.6 / 2018-02-16
|
4
|
+
|
5
|
+
Security fixes:
|
6
|
+
|
7
|
+
* Prevent path traversal when writing to a symlinked basedir outside of the root.
|
8
|
+
Discovered by nmalkin, fixed by Jonathan Claudius and Samuel Giddins.
|
9
|
+
* Fix possible Unsafe Object Deserialization Vulnerability in gem owner.
|
10
|
+
Fixed by Jonathan Claudius.
|
11
|
+
* Strictly interpret octal fields in tar headers.
|
12
|
+
Discoved by plover, fixed by Samuel Giddins.
|
13
|
+
* Raise a security error when there are duplicate files in a package.
|
14
|
+
Discovered by plover, fixed by Samuel Giddins.
|
15
|
+
* Enforce URL validation on spec homepage attribute.
|
16
|
+
Discovered by Yasin Soliman, fixed by Jonathan Claudius.
|
17
|
+
* Mitigate XSS vulnerability in homepage attribute when displayed via `gem server`.
|
18
|
+
Discovered by Yasin Soliman, fixed by Jonathan Claudius.
|
19
|
+
* Prevent Path Traversal issue during gem installation.
|
20
|
+
Discovered by nmalkin.
|
21
|
+
|
3
22
|
=== 2.7.4
|
4
23
|
|
5
24
|
Bug fixes:
|
data/lib/rubygems.rb
CHANGED
data/lib/rubygems/package.rb
CHANGED
@@ -378,7 +378,7 @@ EOM
|
|
378
378
|
File.dirname destination
|
379
379
|
end
|
380
380
|
|
381
|
-
|
381
|
+
mkdir_p_safe mkdir, mkdir_options, destination_dir, entry.full_name
|
382
382
|
|
383
383
|
File.open destination, 'wb' do |out|
|
384
384
|
out.write entry.read
|
@@ -416,20 +416,35 @@ EOM
|
|
416
416
|
raise Gem::Package::PathError.new(filename, destination_dir) if
|
417
417
|
filename.start_with? '/'
|
418
418
|
|
419
|
-
destination_dir =
|
420
|
-
File.respond_to? :realpath
|
419
|
+
destination_dir = realpath destination_dir
|
421
420
|
destination_dir = File.expand_path destination_dir
|
422
421
|
|
423
422
|
destination = File.join destination_dir, filename
|
424
423
|
destination = File.expand_path destination
|
425
424
|
|
426
425
|
raise Gem::Package::PathError.new(destination, destination_dir) unless
|
427
|
-
destination.start_with? destination_dir
|
426
|
+
destination.start_with? destination_dir + '/'
|
428
427
|
|
429
428
|
destination.untaint
|
430
429
|
destination
|
431
430
|
end
|
432
431
|
|
432
|
+
def mkdir_p_safe mkdir, mkdir_options, destination_dir, file_name
|
433
|
+
destination_dir = realpath File.expand_path(destination_dir)
|
434
|
+
parts = mkdir.split(File::SEPARATOR)
|
435
|
+
parts.reduce do |path, basename|
|
436
|
+
path = realpath path unless path == ""
|
437
|
+
path = File.expand_path(path + File::SEPARATOR + basename)
|
438
|
+
lstat = File.lstat path rescue nil
|
439
|
+
if !lstat || !lstat.directory?
|
440
|
+
unless path.start_with? destination_dir and (FileUtils.mkdir path, mkdir_options rescue false)
|
441
|
+
raise Gem::Package::PathError.new(file_name, destination_dir)
|
442
|
+
end
|
443
|
+
end
|
444
|
+
path
|
445
|
+
end
|
446
|
+
end
|
447
|
+
|
433
448
|
##
|
434
449
|
# Loads a Gem::Specification from the TarEntry +entry+
|
435
450
|
|
@@ -603,6 +618,10 @@ EOM
|
|
603
618
|
raise Gem::Package::FormatError.new \
|
604
619
|
'package content (data.tar.gz) is missing', @gem
|
605
620
|
end
|
621
|
+
|
622
|
+
if duplicates = @files.group_by {|f| f }.select {|k,v| v.size > 1 }.map(&:first) and duplicates.any?
|
623
|
+
raise Gem::Security::Exception, "duplicate files in the package: (#{duplicates.map(&:inspect).join(', ')})"
|
624
|
+
end
|
606
625
|
end
|
607
626
|
|
608
627
|
##
|
@@ -616,6 +635,16 @@ EOM
|
|
616
635
|
raise Gem::Package::FormatError.new(e.message, entry.full_name)
|
617
636
|
end
|
618
637
|
|
638
|
+
if File.respond_to? :realpath
|
639
|
+
def realpath file
|
640
|
+
File.realpath file
|
641
|
+
end
|
642
|
+
else
|
643
|
+
def realpath file
|
644
|
+
file
|
645
|
+
end
|
646
|
+
end
|
647
|
+
|
619
648
|
end
|
620
649
|
|
621
650
|
require 'rubygems/package/digest_io'
|
@@ -104,25 +104,30 @@ class Gem::Package::TarHeader
|
|
104
104
|
fields = header.unpack UNPACK_FORMAT
|
105
105
|
|
106
106
|
new :name => fields.shift,
|
107
|
-
:mode => fields.shift
|
108
|
-
:uid => fields.shift
|
109
|
-
:gid => fields.shift
|
110
|
-
:size => fields.shift
|
111
|
-
:mtime => fields.shift
|
112
|
-
:checksum => fields.shift
|
107
|
+
:mode => strict_oct(fields.shift),
|
108
|
+
:uid => strict_oct(fields.shift),
|
109
|
+
:gid => strict_oct(fields.shift),
|
110
|
+
:size => strict_oct(fields.shift),
|
111
|
+
:mtime => strict_oct(fields.shift),
|
112
|
+
:checksum => strict_oct(fields.shift),
|
113
113
|
:typeflag => fields.shift,
|
114
114
|
:linkname => fields.shift,
|
115
115
|
:magic => fields.shift,
|
116
|
-
:version => fields.shift
|
116
|
+
:version => strict_oct(fields.shift),
|
117
117
|
:uname => fields.shift,
|
118
118
|
:gname => fields.shift,
|
119
|
-
:devmajor => fields.shift
|
120
|
-
:devminor => fields.shift
|
119
|
+
:devmajor => strict_oct(fields.shift),
|
120
|
+
:devminor => strict_oct(fields.shift),
|
121
121
|
:prefix => fields.shift,
|
122
122
|
|
123
123
|
:empty => empty
|
124
124
|
end
|
125
125
|
|
126
|
+
def self.strict_oct(str)
|
127
|
+
return str.oct if str =~ /\A[0-7]*\z/
|
128
|
+
raise ArgumentError, "#{str.inspect} is not an octal string"
|
129
|
+
end
|
130
|
+
|
126
131
|
##
|
127
132
|
# Creates a new TarHeader using +vals+
|
128
133
|
|
@@ -196,6 +196,8 @@ class Gem::Package::TarWriter
|
|
196
196
|
digest_name == signer.digest_name
|
197
197
|
end
|
198
198
|
|
199
|
+
raise "no #{signer.digest_name} in #{digests.values.compact}" unless signature_digest
|
200
|
+
|
199
201
|
if signer.key then
|
200
202
|
signature = signer.sign signature_digest.digest
|
201
203
|
|
data/lib/rubygems/server.rb
CHANGED
@@ -623,6 +623,18 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
|
|
623
623
|
executables = nil if executables.empty?
|
624
624
|
executables.last["is_last"] = true if executables
|
625
625
|
|
626
|
+
# Pre-process spec homepage for safety reasons
|
627
|
+
begin
|
628
|
+
homepage_uri = URI.parse(spec.homepage)
|
629
|
+
if [URI::HTTP, URI::HTTPS].member? homepage_uri.class
|
630
|
+
homepage_uri = spec.homepage
|
631
|
+
else
|
632
|
+
homepage_uri = "."
|
633
|
+
end
|
634
|
+
rescue URI::InvalidURIError
|
635
|
+
homepage_uri = "."
|
636
|
+
end
|
637
|
+
|
626
638
|
specs << {
|
627
639
|
"authors" => spec.authors.sort.join(", "),
|
628
640
|
"date" => spec.date.to_s,
|
@@ -632,7 +644,7 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
|
|
632
644
|
"only_one_executable" => (executables && executables.size == 1),
|
633
645
|
"full_name" => spec.full_name,
|
634
646
|
"has_deps" => !deps.empty?,
|
635
|
-
"homepage" =>
|
647
|
+
"homepage" => homepage_uri,
|
636
648
|
"name" => spec.name,
|
637
649
|
"rdoc_installed" => Gem::RDoc.new(spec).rdoc_installed?,
|
638
650
|
"ri_installed" => Gem::RDoc.new(spec).ri_installed?,
|
@@ -15,6 +15,7 @@ require 'rubygems/basic_specification'
|
|
15
15
|
require 'rubygems/stub_specification'
|
16
16
|
require 'rubygems/util/list'
|
17
17
|
require 'stringio'
|
18
|
+
require 'uri'
|
18
19
|
|
19
20
|
##
|
20
21
|
# The Specification class contains the information for a Gem. Typically
|
@@ -2822,10 +2823,16 @@ http://spdx.org/licenses or '#{Gem::Licenses::NONSTANDARD}' for a nonstandard li
|
|
2822
2823
|
raise Gem::InvalidSpecificationException, "#{lazy} is not a summary"
|
2823
2824
|
end
|
2824
2825
|
|
2825
|
-
|
2826
|
-
|
2827
|
-
|
2828
|
-
|
2826
|
+
# Make sure a homepage is valid HTTP/HTTPS URI
|
2827
|
+
if homepage and not homepage.empty?
|
2828
|
+
begin
|
2829
|
+
homepage_uri = URI.parse(homepage)
|
2830
|
+
unless [URI::HTTP, URI::HTTPS].member? homepage_uri.class
|
2831
|
+
raise Gem::InvalidSpecificationException, "\"#{homepage}\" is not a valid HTTP URI"
|
2832
|
+
end
|
2833
|
+
rescue URI::InvalidURIError
|
2834
|
+
raise Gem::InvalidSpecificationException, "\"#{homepage}\" is not a valid HTTP URI"
|
2835
|
+
end
|
2829
2836
|
end
|
2830
2837
|
|
2831
2838
|
# Warnings
|
@@ -43,6 +43,31 @@ EOF
|
|
43
43
|
assert_match %r{- 4}, @ui.output
|
44
44
|
end
|
45
45
|
|
46
|
+
def test_show_owners_dont_load_objects
|
47
|
+
skip "testing a psych-only API" unless defined?(::Psych::DisallowedClass)
|
48
|
+
|
49
|
+
response = <<EOF
|
50
|
+
---
|
51
|
+
- email: !ruby/object:Object {}
|
52
|
+
id: 1
|
53
|
+
handle: user1
|
54
|
+
- email: user2@example.com
|
55
|
+
- id: 3
|
56
|
+
handle: user3
|
57
|
+
- id: 4
|
58
|
+
EOF
|
59
|
+
|
60
|
+
@fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners.yaml"] = [response, 200, 'OK']
|
61
|
+
|
62
|
+
assert_raises Psych::DisallowedClass do
|
63
|
+
use_ui @ui do
|
64
|
+
@cmd.show_owners("freewill")
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
|
46
71
|
def test_show_owners_setting_up_host_through_env_var
|
47
72
|
response = "- email: user1@example.com\n"
|
48
73
|
host = "http://rubygems.example"
|
@@ -455,6 +455,31 @@ class TestGemPackage < Gem::Package::TarTestCase
|
|
455
455
|
File.read(extracted)
|
456
456
|
end
|
457
457
|
|
458
|
+
def test_extract_symlink_parent
|
459
|
+
skip 'symlink not supported' if Gem.win_platform?
|
460
|
+
|
461
|
+
package = Gem::Package.new @gem
|
462
|
+
|
463
|
+
tgz_io = util_tar_gz do |tar|
|
464
|
+
tar.mkdir 'lib', 0755
|
465
|
+
tar.add_symlink 'lib/link', '../..', 0644
|
466
|
+
tar.add_file 'lib/link/outside.txt', 0644 do |io| io.write 'hi' end
|
467
|
+
end
|
468
|
+
|
469
|
+
# Extract into a subdirectory of @destination; if this test fails it writes
|
470
|
+
# a file outside destination_subdir, but we want the file to remain inside
|
471
|
+
# @destination so it will be cleaned up.
|
472
|
+
destination_subdir = File.join @destination, 'subdir'
|
473
|
+
FileUtils.mkdir_p destination_subdir
|
474
|
+
|
475
|
+
e = assert_raises Gem::Package::PathError do
|
476
|
+
package.extract_tar_gz tgz_io, destination_subdir
|
477
|
+
end
|
478
|
+
|
479
|
+
assert_equal("installing into parent path lib/link/outside.txt of " +
|
480
|
+
"#{destination_subdir} is not allowed", e.message)
|
481
|
+
end
|
482
|
+
|
458
483
|
def test_extract_tar_gz_directory
|
459
484
|
package = Gem::Package.new @gem
|
460
485
|
|
@@ -566,6 +591,21 @@ class TestGemPackage < Gem::Package::TarTestCase
|
|
566
591
|
"#{@destination} is not allowed", e.message)
|
567
592
|
end
|
568
593
|
|
594
|
+
def test_install_location_suffix
|
595
|
+
package = Gem::Package.new @gem
|
596
|
+
|
597
|
+
filename = "../#{File.basename(@destination)}suffix.rb"
|
598
|
+
|
599
|
+
e = assert_raises Gem::Package::PathError do
|
600
|
+
package.install_location filename, @destination
|
601
|
+
end
|
602
|
+
|
603
|
+
parent = File.expand_path File.join @destination, filename
|
604
|
+
|
605
|
+
assert_equal("installing into parent path #{parent} of " +
|
606
|
+
"#{@destination} is not allowed", e.message)
|
607
|
+
end
|
608
|
+
|
569
609
|
def test_load_spec
|
570
610
|
entry = StringIO.new Gem.gzip @spec.to_yaml
|
571
611
|
def entry.full_name() 'metadata.gz' end
|
@@ -723,6 +763,32 @@ class TestGemPackage < Gem::Package::TarTestCase
|
|
723
763
|
assert_match %r%nonexistent.gem$%, e.message
|
724
764
|
end
|
725
765
|
|
766
|
+
def test_verify_duplicate_file
|
767
|
+
FileUtils.mkdir_p 'lib'
|
768
|
+
FileUtils.touch 'lib/code.rb'
|
769
|
+
|
770
|
+
build = Gem::Package.new @gem
|
771
|
+
build.spec = @spec
|
772
|
+
build.setup_signer
|
773
|
+
open @gem, 'wb' do |gem_io|
|
774
|
+
Gem::Package::TarWriter.new gem_io do |gem|
|
775
|
+
build.add_metadata gem
|
776
|
+
build.add_contents gem
|
777
|
+
|
778
|
+
gem.add_file_simple 'a.sig', 0444, 0
|
779
|
+
gem.add_file_simple 'a.sig', 0444, 0
|
780
|
+
end
|
781
|
+
end
|
782
|
+
|
783
|
+
package = Gem::Package.new @gem
|
784
|
+
|
785
|
+
e = assert_raises Gem::Security::Exception do
|
786
|
+
package.verify
|
787
|
+
end
|
788
|
+
|
789
|
+
assert_equal 'duplicate files in the package: ("a.sig")', e.message
|
790
|
+
end
|
791
|
+
|
726
792
|
def test_verify_security_policy
|
727
793
|
skip 'openssl is missing' unless defined?(OpenSSL::SSL)
|
728
794
|
|
@@ -780,7 +846,13 @@ class TestGemPackage < Gem::Package::TarTestCase
|
|
780
846
|
|
781
847
|
# write bogus data.tar.gz to foil signature
|
782
848
|
bogus_data = Gem.gzip 'hello'
|
783
|
-
|
849
|
+
fake_signer = Class.new do
|
850
|
+
def digest_name; 'SHA512'; end
|
851
|
+
def digest_algorithm; Digest(:SHA512); end
|
852
|
+
def key; 'key'; end
|
853
|
+
def sign(*); 'fake_sig'; end
|
854
|
+
end
|
855
|
+
gem.add_file_signed 'data2.tar.gz', 0444, fake_signer.new do |io|
|
784
856
|
io.write bogus_data
|
785
857
|
end
|
786
858
|
|
@@ -143,5 +143,25 @@ group\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
|
|
143
143
|
assert_equal '012467', @tar_header.checksum
|
144
144
|
end
|
145
145
|
|
146
|
+
def test_from_bad_octal
|
147
|
+
test_cases = [
|
148
|
+
"00000006,44\000", # bogus character
|
149
|
+
"00000006789\000", # non-octal digit
|
150
|
+
"+0000001234\000", # positive sign
|
151
|
+
"-0000001000\000", # negative sign
|
152
|
+
"0x000123abc\000", # radix prefix
|
153
|
+
]
|
154
|
+
|
155
|
+
test_cases.each do |val|
|
156
|
+
header_s = @tar_header.to_s
|
157
|
+
# overwrite the size field
|
158
|
+
header_s[124, 12] = val
|
159
|
+
io = TempIO.new header_s
|
160
|
+
assert_raises ArgumentError do
|
161
|
+
new_header = Gem::Package::TarHeader.from io
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
146
166
|
end
|
147
167
|
|
@@ -353,6 +353,171 @@ class TestGemServer < Gem::TestCase
|
|
353
353
|
assert_match 'z 9', @res.body
|
354
354
|
end
|
355
355
|
|
356
|
+
|
357
|
+
def test_xss_homepage_fix_289313
|
358
|
+
data = StringIO.new "GET / HTTP/1.0\r\n\r\n"
|
359
|
+
dir = "#{@gemhome}2"
|
360
|
+
|
361
|
+
spec = util_spec 'xsshomepagegem', 1
|
362
|
+
spec.homepage = "javascript:confirm(document.domain)"
|
363
|
+
|
364
|
+
specs_dir = File.join dir, 'specifications'
|
365
|
+
FileUtils.mkdir_p specs_dir
|
366
|
+
|
367
|
+
open File.join(specs_dir, spec.spec_name), 'w' do |io|
|
368
|
+
io.write spec.to_ruby
|
369
|
+
end
|
370
|
+
|
371
|
+
server = Gem::Server.new dir, process_based_port, false
|
372
|
+
|
373
|
+
@req.parse data
|
374
|
+
|
375
|
+
server.root @req, @res
|
376
|
+
|
377
|
+
assert_equal 200, @res.status
|
378
|
+
assert_match 'xsshomepagegem 1', @res.body
|
379
|
+
|
380
|
+
# This verifies that the homepage for this spec is not displayed and is set to ".", because it's not a
|
381
|
+
# valid HTTP/HTTPS URL and could be unsafe in an HTML context. We would prefer to throw an exception here,
|
382
|
+
# but spec.homepage is currently free form and not currently required to be a URL, this behavior may be
|
383
|
+
# validated in future versions of Gem::Specification.
|
384
|
+
#
|
385
|
+
# There are two variant we're checking here, one where rdoc is not present, and one where rdoc is present in the same regex:
|
386
|
+
#
|
387
|
+
# Variant #1 - rdoc not installed
|
388
|
+
#
|
389
|
+
# <b>xsshomepagegem 1</b>
|
390
|
+
#
|
391
|
+
#
|
392
|
+
# <span title="rdoc not installed">[rdoc]</span>
|
393
|
+
#
|
394
|
+
#
|
395
|
+
#
|
396
|
+
# <a href="." title=".">[www]</a>
|
397
|
+
#
|
398
|
+
# Variant #2 - rdoc installed
|
399
|
+
#
|
400
|
+
# <b>xsshomepagegem 1</b>
|
401
|
+
#
|
402
|
+
#
|
403
|
+
# <a href="\/doc_root\/xsshomepagegem-1\/">\[rdoc\]<\/a>
|
404
|
+
#
|
405
|
+
#
|
406
|
+
#
|
407
|
+
# <a href="." title=".">[www]</a>
|
408
|
+
regex_match = /xsshomepagegem 1<\/b>[\n\s]+(<span title="rdoc not installed">\[rdoc\]<\/span>|<a href="\/doc_root\/xsshomepagegem-1\/">\[rdoc\]<\/a>)[\n\s]+<a href="\." title="\.">\[www\]<\/a>/
|
409
|
+
assert_match regex_match, @res.body
|
410
|
+
end
|
411
|
+
|
412
|
+
def test_invalid_homepage
|
413
|
+
data = StringIO.new "GET / HTTP/1.0\r\n\r\n"
|
414
|
+
dir = "#{@gemhome}2"
|
415
|
+
|
416
|
+
spec = util_spec 'invalidhomepagegem', 1
|
417
|
+
spec.homepage = "notavalidhomepageurl"
|
418
|
+
|
419
|
+
specs_dir = File.join dir, 'specifications'
|
420
|
+
FileUtils.mkdir_p specs_dir
|
421
|
+
|
422
|
+
open File.join(specs_dir, spec.spec_name), 'w' do |io|
|
423
|
+
io.write spec.to_ruby
|
424
|
+
end
|
425
|
+
|
426
|
+
server = Gem::Server.new dir, process_based_port, false
|
427
|
+
|
428
|
+
@req.parse data
|
429
|
+
|
430
|
+
server.root @req, @res
|
431
|
+
|
432
|
+
assert_equal 200, @res.status
|
433
|
+
assert_match 'invalidhomepagegem 1', @res.body
|
434
|
+
|
435
|
+
# This verifies that the homepage for this spec is not displayed and is set to ".", because it's not a
|
436
|
+
# valid HTTP/HTTPS URL and could be unsafe in an HTML context. We would prefer to throw an exception here,
|
437
|
+
# but spec.homepage is currently free form and not currently required to be a URL, this behavior may be
|
438
|
+
# validated in future versions of Gem::Specification.
|
439
|
+
#
|
440
|
+
# There are two variant we're checking here, one where rdoc is not present, and one where rdoc is present in the same regex:
|
441
|
+
#
|
442
|
+
# Variant #1 - rdoc not installed
|
443
|
+
#
|
444
|
+
# <b>invalidhomepagegem 1</b>
|
445
|
+
#
|
446
|
+
#
|
447
|
+
# <span title="rdoc not installed">[rdoc]</span>
|
448
|
+
#
|
449
|
+
#
|
450
|
+
#
|
451
|
+
# <a href="." title=".">[www]</a>
|
452
|
+
#
|
453
|
+
# Variant #2 - rdoc installed
|
454
|
+
#
|
455
|
+
# <b>invalidhomepagegem 1</b>
|
456
|
+
#
|
457
|
+
#
|
458
|
+
# <a href="\/doc_root\/invalidhomepagegem-1\/">\[rdoc\]<\/a>
|
459
|
+
#
|
460
|
+
#
|
461
|
+
#
|
462
|
+
# <a href="." title=".">[www]</a>
|
463
|
+
regex_match = /invalidhomepagegem 1<\/b>[\n\s]+(<span title="rdoc not installed">\[rdoc\]<\/span>|<a href="\/doc_root\/invalidhomepagegem-1\/">\[rdoc\]<\/a>)[\n\s]+<a href="\." title="\.">\[www\]<\/a>/
|
464
|
+
assert_match regex_match, @res.body
|
465
|
+
end
|
466
|
+
|
467
|
+
def test_valid_homepage_http
|
468
|
+
data = StringIO.new "GET / HTTP/1.0\r\n\r\n"
|
469
|
+
dir = "#{@gemhome}2"
|
470
|
+
|
471
|
+
spec = util_spec 'validhomepagegemhttp', 1
|
472
|
+
spec.homepage = "http://rubygems.org"
|
473
|
+
|
474
|
+
specs_dir = File.join dir, 'specifications'
|
475
|
+
FileUtils.mkdir_p specs_dir
|
476
|
+
|
477
|
+
open File.join(specs_dir, spec.spec_name), 'w' do |io|
|
478
|
+
io.write spec.to_ruby
|
479
|
+
end
|
480
|
+
|
481
|
+
server = Gem::Server.new dir, process_based_port, false
|
482
|
+
|
483
|
+
@req.parse data
|
484
|
+
|
485
|
+
server.root @req, @res
|
486
|
+
|
487
|
+
assert_equal 200, @res.status
|
488
|
+
assert_match 'validhomepagegemhttp 1', @res.body
|
489
|
+
|
490
|
+
regex_match = /validhomepagegemhttp 1<\/b>[\n\s]+(<span title="rdoc not installed">\[rdoc\]<\/span>|<a href="\/doc_root\/validhomepagegemhttp-1\/">\[rdoc\]<\/a>)[\n\s]+<a href="http:\/\/rubygems\.org" title="http:\/\/rubygems\.org">\[www\]<\/a>/
|
491
|
+
assert_match regex_match, @res.body
|
492
|
+
end
|
493
|
+
|
494
|
+
def test_valid_homepage_https
|
495
|
+
data = StringIO.new "GET / HTTP/1.0\r\n\r\n"
|
496
|
+
dir = "#{@gemhome}2"
|
497
|
+
|
498
|
+
spec = util_spec 'validhomepagegemhttps', 1
|
499
|
+
spec.homepage = "https://rubygems.org"
|
500
|
+
|
501
|
+
specs_dir = File.join dir, 'specifications'
|
502
|
+
FileUtils.mkdir_p specs_dir
|
503
|
+
|
504
|
+
open File.join(specs_dir, spec.spec_name), 'w' do |io|
|
505
|
+
io.write spec.to_ruby
|
506
|
+
end
|
507
|
+
|
508
|
+
server = Gem::Server.new dir, process_based_port, false
|
509
|
+
|
510
|
+
@req.parse data
|
511
|
+
|
512
|
+
server.root @req, @res
|
513
|
+
|
514
|
+
assert_equal 200, @res.status
|
515
|
+
assert_match 'validhomepagegemhttps 1', @res.body
|
516
|
+
|
517
|
+
regex_match = /validhomepagegemhttps 1<\/b>[\n\s]+(<span title="rdoc not installed">\[rdoc\]<\/span>|<a href="\/doc_root\/validhomepagegemhttps-1\/">\[rdoc\]<\/a>)[\n\s]+<a href="https:\/\/rubygems\.org" title="https:\/\/rubygems\.org">\[www\]<\/a>/
|
518
|
+
assert_match regex_match, @res.body
|
519
|
+
end
|
520
|
+
|
356
521
|
def test_specs
|
357
522
|
data = StringIO.new "GET /specs.#{Gem.marshal_version} HTTP/1.0\r\n\r\n"
|
358
523
|
@req.parse data
|
@@ -2886,7 +2886,22 @@ duplicate dependency on c (>= 1.2.3, development), (~> 1.2) use:
|
|
2886
2886
|
@a1.validate
|
2887
2887
|
end
|
2888
2888
|
|
2889
|
-
assert_equal '"over at my cool site" is not a URI', e.message
|
2889
|
+
assert_equal '"over at my cool site" is not a valid HTTP URI', e.message
|
2890
|
+
|
2891
|
+
@a1.homepage = 'ftp://rubygems.org'
|
2892
|
+
|
2893
|
+
e = assert_raises Gem::InvalidSpecificationException do
|
2894
|
+
@a1.validate
|
2895
|
+
end
|
2896
|
+
|
2897
|
+
assert_equal '"ftp://rubygems.org" is not a valid HTTP URI', e.message
|
2898
|
+
|
2899
|
+
@a1.homepage = 'http://rubygems.org'
|
2900
|
+
assert_equal true, @a1.validate
|
2901
|
+
|
2902
|
+
@a1.homepage = 'https://rubygems.org'
|
2903
|
+
assert_equal true, @a1.validate
|
2904
|
+
|
2890
2905
|
end
|
2891
2906
|
end
|
2892
2907
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubygems-update
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.7.
|
4
|
+
version: 2.7.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jim Weirich
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2018-02-
|
13
|
+
date: 2018-02-16 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: builder
|
@@ -804,7 +804,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
804
804
|
version: '0'
|
805
805
|
requirements: []
|
806
806
|
rubyforge_project:
|
807
|
-
rubygems_version: 2.7.
|
807
|
+
rubygems_version: 2.7.4
|
808
808
|
signing_key:
|
809
809
|
specification_version: 4
|
810
810
|
summary: ''
|