From a2560b80ba7c913d90302258910b3216ce96ecf9 Mon Sep 17 00:00:00 2001 From: Max Felsher <126290603+maxfelsher-cgi@users.noreply.github.com> Date: Thu, 21 May 2026 21:35:13 +0000 Subject: [PATCH] Do not hard-code permissions for new gem directories during bundle install This hard-coding was overriding umask and setgid settings, making it very difficult to manage gem installations through a shared group. In addition, it differs from the behavior of `gem install`. The hard-coding was originally added in 79386f4 as part of an unrelated reimplementation of `Bundler::RubyGemsGemInstaller#install`, but it looks like the logic on the corresponding line of `Gem::Installer#install` might have been misinterpreted, as that line only sets the `mode` argument if `options[:dir_mode]` is set. --- bundler/lib/bundler/rubygems_gem_installer.rb | 2 +- spec/commands/install_spec.rb | 31 +++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/bundler/lib/bundler/rubygems_gem_installer.rb b/bundler/lib/bundler/rubygems_gem_installer.rb index e4dd2d95afa3..fc019f54d240 100644 --- a/bundler/lib/bundler/rubygems_gem_installer.rb +++ b/bundler/lib/bundler/rubygems_gem_installer.rb @@ -20,7 +20,7 @@ def install strict_rm_rf spec.extension_dir SharedHelpers.filesystem_access(gem_dir, :create) do - FileUtils.mkdir_p gem_dir, mode: 0o755 + FileUtils.mkdir_p gem_dir end SharedHelpers.filesystem_access(gem_dir, :write) do diff --git a/spec/commands/install_spec.rb b/spec/commands/install_spec.rb index 8dedeb7d0776..74b046b708ba 100644 --- a/spec/commands/install_spec.rb +++ b/spec/commands/install_spec.rb @@ -1306,6 +1306,37 @@ def run end end + describe "when using umask 002 and setgid bit", :permissions do + let(:gems_path) { bundled_app("vendor/#{Bundler.ruby_scope}/gems") } + let(:foo_path) { gems_path.join("foo-1.0.0") } + + before do + build_repo4 do + build_gem "foo", "1.0.0" do |s| + s.write "CHANGELOG.md", "foo" + end + end + + gemfile <<-G + source "https://gem.repo4" + gem 'foo' + G + + FileUtils.mkdir_p(gems_path) + FileUtils.chmod("g+s", gems_path) + end + + it "should create the gem directory with proper permissions" do + with_umask(0o002) do + bundle_config "path vendor" + bundle :install + expect(out).to include("Bundle complete!") + expect(err).to be_empty + expect(File.stat(foo_path).mode & 0o7777).to eq(0o2775) + end + end + end + describe "parallel make" do before do unless Gem::Installer.private_method_defined?(:build_jobs)