Skip to content

Commit 9f32631

Browse files
hsbtclaude
andcommitted
Escape executable name when generating the wrapper script
Escape the executable name interpolated into the generated wrapper so a name containing quotes cannot change the generated Ruby. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent cd61a78 commit 9f32631

2 files changed

Lines changed: 18 additions & 2 deletions

File tree

lib/rubygems/installer.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -730,6 +730,7 @@ def verify_spec
730730
def app_script_text(bin_file_name)
731731
# NOTE: that the `load` lines cannot be indented, as old RG versions match
732732
# against the beginning of the line
733+
escaped_bin_file_name = bin_file_name.gsub(/[\\']/) {|c| "\\#{c}" }
733734
<<~TEXT
734735
#{shebang bin_file_name}
735736
#
@@ -753,9 +754,9 @@ def app_script_text(bin_file_name)
753754
end
754755
755756
if Gem.respond_to?(:activate_and_load_bin_path)
756-
Gem.activate_and_load_bin_path('#{spec.name}', '#{bin_file_name}', version)
757+
Gem.activate_and_load_bin_path('#{spec.name}', '#{escaped_bin_file_name}', version)
757758
else
758-
load Gem.activate_bin_path('#{spec.name}', '#{bin_file_name}', version)
759+
load Gem.activate_bin_path('#{spec.name}', '#{escaped_bin_file_name}', version)
759760
end
760761
TEXT
761762
end

test/rubygems/test_gem_installer.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,21 @@ def test_app_script_text
6060
end
6161
end
6262

63+
def test_app_script_text_escapes_executable_name
64+
installer = setup_base_installer
65+
66+
malicious = "evil');system('id');#"
67+
@spec.bindir = "bin"
68+
write_file @spec.bin_file(malicious) do |io|
69+
io.puts "#!/usr/bin/ruby"
70+
end
71+
72+
wrapper = installer.app_script_text malicious
73+
74+
assert_includes wrapper, %q{Gem.activate_and_load_bin_path('a', 'evil\');system(\'id\');#', version)}
75+
assert_includes wrapper, %q{load Gem.activate_bin_path('a', 'evil\');system(\'id\');#', version)}
76+
end
77+
6378
def test_check_executable_overwrite
6479
installer = setup_base_installer
6580

0 commit comments

Comments
 (0)