Blob Blame History Raw
From 65cfebb041c454c246aaf32a177b0243915a9998 Mon Sep 17 00:00:00 2001
From: fatkodima <fatkodima123@gmail.com>
Date: Fri, 1 Nov 2019 23:06:10 +0200
Subject: [PATCH] Don't use insecure temporary directory as home directory

---
 lib/bundler.rb                | 29 +++++++++++---------------
 spec/bundler/bundler_spec.rb  | 38 +++++++++--------------------------
 spec/bundler/settings_spec.rb |  2 +-
 3 files changed, 22 insertions(+), 47 deletions(-)

diff --git a/lib/bundler.rb b/lib/bundler.rb
index 2ada6fe7891..b184f7e69c6 100644
--- a/lib/bundler.rb
+++ b/lib/bundler.rb
@@ -170,8 +170,7 @@ def user_home
         end
 
         if warning
-          Kernel.send(:require, "etc")
-          user_home = tmp_home_path(Etc.getlogin, warning)
+          user_home = tmp_home_path(warning)
           Bundler.ui.warn "#{warning}\nBundler will use `#{user_home}' as your home directory temporarily.\n"
           user_home
         else
@@ -180,21 +180,6 @@ def user_home
       end
     end
 
-    def tmp_home_path(login, warning)
-      login ||= "unknown"
-      Kernel.send(:require, "tmpdir")
-      path = Pathname.new(Dir.tmpdir).join("bundler", "home")
-      SharedHelpers.filesystem_access(path) do |tmp_home_path|
-        unless tmp_home_path.exist?
-          tmp_home_path.mkpath
-          tmp_home_path.chmod(0o777)
-        end
-        tmp_home_path.join(login).tap(&:mkpath)
-      end
-    rescue RuntimeError => e
-      raise e.exception("#{warning}\nBundler also failed to create a temporary home directory at `#{path}':\n#{e}")
-    end
-
     def user_bundle_path(dir = "home")
       env_var, fallback = case dir
                           when "home"
@@ -555,6 +555,17 @@ def configure_gem_home
       Bundler.rubygems.clear_paths
     end
 
+    def tmp_home_path(warning)
+      Kernel.send(:require, "tmpdir")
+      SharedHelpers.filesystem_access(Dir.tmpdir) do
+        path = Bundler.tmp
+        at_exit { Bundler.rm_rf(path) }
+        path
+      end
+    rescue RuntimeError => e
+      raise e.exception("#{warning}\nBundler also failed to create a temporary home directory':\n#{e}")
+    end
+
     # @param env [Hash]
     def with_env(env)
       backup = ENV.to_hash
diff --git a/spec/bundler/bundler/bundler_spec.rb b/spec/bundler/bundler/bundler_spec.rb
index 74cf7ae05d3..247838600bf 100644
--- a/spec/bundler/bundler/bundler_spec.rb
+++ b/spec/bundler/bundler/bundler_spec.rb
@@ -233,16 +233,13 @@
           path = "/home/oggy"
           allow(Bundler.rubygems).to receive(:user_home).and_return(path)
           allow(File).to receive(:directory?).with(path).and_return false
-          allow(Etc).to receive(:getlogin).and_return("USER")
-          allow(Dir).to receive(:tmpdir).and_return("/TMP")
-          allow(FileTest).to receive(:exist?).with("/TMP/bundler/home").and_return(true)
-          expect(FileUtils).to receive(:mkpath).with("/TMP/bundler/home/USER")
+          allow(Bundler).to receive(:tmp).and_return(Pathname.new("/tmp/trulyrandom"))
           message = <<EOF
 `/home/oggy` is not a directory.
-Bundler will use `/TMP/bundler/home/USER' as your home directory temporarily.
+Bundler will use `/tmp/trulyrandom' as your home directory temporarily.
 EOF
           expect(Bundler.ui).to receive(:warn).with(message)
-          expect(Bundler.user_home).to eq(Pathname("/TMP/bundler/home/USER"))
+          expect(Bundler.user_home).to eq(Pathname("/tmp/trulyrandom"))
         end
       end
 
@@ -255,16 +252,13 @@
           allow(File).to receive(:directory?).with(path).and_return true
           allow(File).to receive(:writable?).with(path).and_return false
           allow(File).to receive(:directory?).with(dotbundle).and_return false
-          allow(Etc).to receive(:getlogin).and_return("USER")
-          allow(Dir).to receive(:tmpdir).and_return("/TMP")
-          allow(FileTest).to receive(:exist?).with("/TMP/bundler/home").and_return(true)
-          expect(FileUtils).to receive(:mkpath).with("/TMP/bundler/home/USER")
+          allow(Bundler).to receive(:tmp).and_return(Pathname.new("/tmp/trulyrandom"))
           message = <<EOF
 `/home/oggy` is not writable.
-Bundler will use `/TMP/bundler/home/USER' as your home directory temporarily.
+Bundler will use `/tmp/trulyrandom' as your home directory temporarily.
 EOF
           expect(Bundler.ui).to receive(:warn).with(message)
-          expect(Bundler.user_home).to eq(Pathname("/TMP/bundler/home/USER"))
+          expect(Bundler.user_home).to eq(Pathname("/tmp/trulyrandom"))
         end
 
         context ".bundle exists and have correct permissions" do
@@ -283,31 +277,17 @@
     context "home directory is not set" do
       it "should issue warning and return a temporary user home" do
         allow(Bundler.rubygems).to receive(:user_home).and_return(nil)
-        allow(Etc).to receive(:getlogin).and_return("USER")
-        allow(Dir).to receive(:tmpdir).and_return("/TMP")
-        allow(FileTest).to receive(:exist?).with("/TMP/bundler/home").and_return(true)
-        expect(FileUtils).to receive(:mkpath).with("/TMP/bundler/home/USER")
+        allow(Bundler).to receive(:tmp).and_return(Pathname.new("/tmp/trulyrandom"))
         message = <<EOF
 Your home directory is not set.
-Bundler will use `/TMP/bundler/home/USER' as your home directory temporarily.
+Bundler will use `/tmp/trulyrandom' as your home directory temporarily.
 EOF
         expect(Bundler.ui).to receive(:warn).with(message)
-        expect(Bundler.user_home).to eq(Pathname("/TMP/bundler/home/USER"))
+        expect(Bundler.user_home).to eq(Pathname("/tmp/trulyrandom"))
       end
     end
   end
 
-  describe "#tmp_home_path" do
-    it "should create temporary user home" do
-      allow(Dir).to receive(:tmpdir).and_return("/TMP")
-      allow(FileTest).to receive(:exist?).with("/TMP/bundler/home").and_return(false)
-      expect(FileUtils).to receive(:mkpath).once.ordered.with("/TMP/bundler/home")
-      expect(FileUtils).to receive(:mkpath).once.ordered.with("/TMP/bundler/home/USER")
-      expect(File).to receive(:chmod).with(0o777, "/TMP/bundler/home")
-      expect(Bundler.tmp_home_path("USER", "")).to eq(Pathname("/TMP/bundler/home/USER"))
-    end
-  end
-
   describe "#requires_sudo?" do
     let!(:tmpdir) { Dir.mktmpdir }
     let(:bundle_path) { Pathname("#{tmpdir}/bundle") }
diff --git a/spec/bundler/bundler/settings_spec.rb b/spec/bundler/bundler/settings_spec.rb
index 7e1dadded76..2a285fdcf37 100644
--- a/spec/bundler/bundler/settings_spec.rb
+++ b/spec/bundler/bundler/settings_spec.rb
@@ -67,7 +67,7 @@
       context "when $TMPDIR is not writable" do
         it "does not raise" do
           expect(Bundler.rubygems).to receive(:user_home).twice.and_return(nil)
-          expect(FileUtils).to receive(:mkpath).twice.with(File.join(Dir.tmpdir, "bundler", "home")).and_raise(Errno::EROFS, "Read-only file system @ dir_s_mkdir - /tmp/bundler")
+          expect(Bundler).to receive(:tmp).twice.and_raise(Errno::EROFS, "Read-only file system @ dir_s_mkdir - /tmp/bundler")
 
           expect(subject.send(:global_config_file)).to be_nil
         end