Skip to content

Commit 44cc27c

Browse files
committed
Validate specification names
This will validate that specification names are restricted to those that rubygems.org will accept, and provide a superior experience when users accidentally include invalid characters in the name compared to an invalid push or a failing install
1 parent 8a38a4f commit 44cc27c

File tree

2 files changed

+41
-3
lines changed

2 files changed

+41
-3
lines changed

lib/rubygems/specification.rb

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ class Gem::Specification < Gem::BasicSpecification
108108

109109
private_constant :LOAD_CACHE if defined? private_constant
110110

111+
VALID_NAME_PATTERN = /\A[a-zA-Z0-9\.\-\_]+\z/ # :nodoc:
112+
111113
# :startdoc:
112114

113115
##
@@ -2668,9 +2670,15 @@ def validate packaging = true
26682670
end
26692671
end
26702672

2671-
unless String === name then
2673+
if !name.is_a?(String) then
2674+
raise Gem::InvalidSpecificationException,
2675+
"invalid value for attribute name: \"#{name.inspect}\" must be a string"
2676+
elsif name !~ /[a-zA-Z]/ then
2677+
raise Gem::InvalidSpecificationException,
2678+
"invalid value for attribute name: #{name.dump} must include at least one letter"
2679+
elsif name !~ VALID_NAME_PATTERN then
26722680
raise Gem::InvalidSpecificationException,
2673-
"invalid value for attribute name: \"#{name.inspect}\""
2681+
"invalid value for attribute name: #{name.dump} can only include letters, numbers, dashes, and underscores"
26742682
end
26752683

26762684
if raw_require_paths.empty? then

test/rubygems/test_gem_specification.rb

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2985,7 +2985,37 @@ def test_validate_name
29852985
@a1.validate
29862986
end
29872987

2988-
assert_equal 'invalid value for attribute name: ":json"', e.message
2988+
assert_equal 'invalid value for attribute name: ":json" must be a string', e.message
2989+
2990+
@a1.name = []
2991+
e = assert_raises Gem::InvalidSpecificationException do
2992+
@a1.validate
2993+
end
2994+
assert_equal "invalid value for attribute name: \"[]\" must be a string", e.message
2995+
2996+
@a1.name = ""
2997+
e = assert_raises Gem::InvalidSpecificationException do
2998+
@a1.validate
2999+
end
3000+
assert_equal "invalid value for attribute name: \"\" must include at least one letter", e.message
3001+
3002+
@a1.name = "12345"
3003+
e = assert_raises Gem::InvalidSpecificationException do
3004+
@a1.validate
3005+
end
3006+
assert_equal "invalid value for attribute name: \"12345\" must include at least one letter", e.message
3007+
3008+
@a1.name = "../malicious"
3009+
e = assert_raises Gem::InvalidSpecificationException do
3010+
@a1.validate
3011+
end
3012+
assert_equal "invalid value for attribute name: \"../malicious\" can only include letters, numbers, dashes, and underscores", e.message
3013+
3014+
@a1.name = "\ba\t"
3015+
e = assert_raises Gem::InvalidSpecificationException do
3016+
@a1.validate
3017+
end
3018+
assert_equal "invalid value for attribute name: \"\\ba\\t\" can only include letters, numbers, dashes, and underscores", e.message
29893019
end
29903020

29913021
def test_validate_non_nil

0 commit comments

Comments
 (0)