Skip to content

Commit 89bf13a

Browse files
hsbtclaude
andcommitted
Reject non-String executables and bindir with a clear error
A non-String executable name or bindir previously raised TypeError from File.basename or File.join. Guard the type so verify_spec raises Gem::InstallError instead of aborting with an unexpected exception. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 9f32631 commit 89bf13a

2 files changed

Lines changed: 35 additions & 1 deletion

File tree

lib/rubygems/installer.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -713,10 +713,12 @@ def verify_spec
713713
raise Gem::InstallError, "#{spec} has an invalid dependencies"
714714
end
715715

716-
if spec.executables.any? {|name| name != File.basename(name) || /\A\.\.?\z|\R/.match?(name) }
716+
if spec.executables.any? {|name| !name.is_a?(String) || name != File.basename(name) || /\A\.\.?\z|\R/.match?(name) }
717717
raise Gem::InstallError, "#{spec} has an invalid executable"
718718
end
719719

720+
raise Gem::InstallError, "#{spec} has an invalid bindir" unless spec.bindir.is_a?(String)
721+
720722
expanded_gem_dir = File.expand_path(gem_dir)
721723
expanded_bindir = File.expand_path(File.join(gem_dir, spec.bindir))
722724
unless expanded_bindir == expanded_gem_dir || expanded_bindir.start_with?("#{expanded_gem_dir}/")

test/rubygems/test_gem_installer.rb

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1980,6 +1980,38 @@ def spec.validate(*args); end
19801980
end
19811981
end
19821982

1983+
def test_pre_install_checks_non_string_executable
1984+
spec = util_spec "malicious", "1"
1985+
def spec.validate(*args); end
1986+
spec.executables = [nil]
1987+
1988+
installer = Gem::Installer.for_spec spec
1989+
installer.gem_home = @gemhome
1990+
1991+
use_ui @ui do
1992+
e = assert_raise Gem::InstallError do
1993+
installer.pre_install_checks
1994+
end
1995+
assert_equal "#<Gem::Specification name=malicious version=1> has an invalid executable", e.message
1996+
end
1997+
end
1998+
1999+
def test_pre_install_checks_non_string_bindir
2000+
spec = util_spec "malicious", "1"
2001+
def spec.validate(*args); end
2002+
spec.bindir = true
2003+
2004+
installer = Gem::Installer.for_spec spec
2005+
installer.gem_home = @gemhome
2006+
2007+
use_ui @ui do
2008+
e = assert_raise Gem::InstallError do
2009+
installer.pre_install_checks
2010+
end
2011+
assert_equal "#<Gem::Specification name=malicious version=1> has an invalid bindir", e.message
2012+
end
2013+
end
2014+
19832015
def test_pre_install_checks_malicious_platform_before_eval
19842016
gem_with_ill_formatted_platform = File.expand_path("packages/ill-formatted-platform-1.0.0.10.gem", __dir__)
19852017

0 commit comments

Comments
 (0)