[ruby/rubygems] 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.

https://github.com/ruby/rubygems/commit/89bf13a11b

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Hiroshi SHIBATA 2026-06-04 18:45:18 +09:00 committed by git
parent daa3721f02
commit cf90fbfed2
2 changed files with 35 additions and 1 deletions

View File

@ -713,10 +713,12 @@ class Gem::Installer
raise Gem::InstallError, "#{spec} has an invalid dependencies"
end
if spec.executables.any? {|name| name != File.basename(name) || /\A\.\.?\z|\R/.match?(name) }
if spec.executables.any? {|name| !name.is_a?(String) || name != File.basename(name) || /\A\.\.?\z|\R/.match?(name) }
raise Gem::InstallError, "#{spec} has an invalid executable"
end
raise Gem::InstallError, "#{spec} has an invalid bindir" unless spec.bindir.is_a?(String)
expanded_gem_dir = File.expand_path(gem_dir)
expanded_bindir = File.expand_path(File.join(gem_dir, spec.bindir))
unless expanded_bindir == expanded_gem_dir || expanded_bindir.start_with?("#{expanded_gem_dir}/")

View File

@ -2013,6 +2013,38 @@ class TestGemInstaller < Gem::InstallerTestCase
end
end
def test_pre_install_checks_non_string_executable
spec = util_spec "malicious", "1"
def spec.validate(*args); end
spec.executables = [nil]
installer = Gem::Installer.for_spec spec
installer.gem_home = @gemhome
use_ui @ui do
e = assert_raise Gem::InstallError do
installer.pre_install_checks
end
assert_equal "#<Gem::Specification name=malicious version=1> has an invalid executable", e.message
end
end
def test_pre_install_checks_non_string_bindir
spec = util_spec "malicious", "1"
def spec.validate(*args); end
spec.bindir = true
installer = Gem::Installer.for_spec spec
installer.gem_home = @gemhome
use_ui @ui do
e = assert_raise Gem::InstallError do
installer.pre_install_checks
end
assert_equal "#<Gem::Specification name=malicious version=1> has an invalid bindir", e.message
end
end
def test_pre_install_checks_malicious_platform_before_eval
gem_with_ill_formatted_platform = File.expand_path("packages/ill-formatted-platform-1.0.0.10.gem", __dir__)