c99b38
From 65cfebb041c454c246aaf32a177b0243915a9998 Mon Sep 17 00:00:00 2001
c99b38
From: fatkodima <fatkodima123@gmail.com>
c99b38
Date: Fri, 1 Nov 2019 23:06:10 +0200
c99b38
Subject: [PATCH] Don't use insecure temporary directory as home directory
c99b38
c99b38
---
c99b38
 lib/bundler.rb                | 29 +++++++++++---------------
c99b38
 spec/bundler/bundler_spec.rb  | 38 +++++++++--------------------------
c99b38
 spec/bundler/settings_spec.rb |  2 +-
c99b38
 3 files changed, 22 insertions(+), 47 deletions(-)
c99b38
c99b38
diff --git a/lib/bundler.rb b/lib/bundler.rb
c99b38
index 2ada6fe7891..b184f7e69c6 100644
c99b38
--- a/lib/bundler.rb
c99b38
+++ b/lib/bundler.rb
c99b38
@@ -170,8 +170,7 @@ def user_home
c99b38
         end
c99b38
 
c99b38
         if warning
c99b38
-          Kernel.send(:require, "etc")
c99b38
-          user_home = tmp_home_path(Etc.getlogin, warning)
c99b38
+          user_home = tmp_home_path(warning)
c99b38
           Bundler.ui.warn "#{warning}\nBundler will use `#{user_home}' as your home directory temporarily.\n"
c99b38
           user_home
c99b38
         else
c99b38
@@ -180,21 +180,6 @@ def user_home
c99b38
       end
c99b38
     end
c99b38
 
c99b38
-    def tmp_home_path(login, warning)
c99b38
-      login ||= "unknown"
c99b38
-      Kernel.send(:require, "tmpdir")
c99b38
-      path = Pathname.new(Dir.tmpdir).join("bundler", "home")
c99b38
-      SharedHelpers.filesystem_access(path) do |tmp_home_path|
c99b38
-        unless tmp_home_path.exist?
c99b38
-          tmp_home_path.mkpath
c99b38
-          tmp_home_path.chmod(0o777)
c99b38
-        end
c99b38
-        tmp_home_path.join(login).tap(&:mkpath)
c99b38
-      end
c99b38
-    rescue RuntimeError => e
c99b38
-      raise e.exception("#{warning}\nBundler also failed to create a temporary home directory at `#{path}':\n#{e}")
c99b38
-    end
c99b38
-
c99b38
     def user_bundle_path(dir = "home")
c99b38
       env_var, fallback = case dir
c99b38
                           when "home"
c99b38
@@ -555,6 +555,17 @@ def configure_gem_home
c99b38
       Bundler.rubygems.clear_paths
c99b38
     end
c99b38
 
c99b38
+    def tmp_home_path(warning)
c99b38
+      Kernel.send(:require, "tmpdir")
c99b38
+      SharedHelpers.filesystem_access(Dir.tmpdir) do
c99b38
+        path = Bundler.tmp
c99b38
+        at_exit { Bundler.rm_rf(path) }
c99b38
+        path
c99b38
+      end
c99b38
+    rescue RuntimeError => e
c99b38
+      raise e.exception("#{warning}\nBundler also failed to create a temporary home directory':\n#{e}")
c99b38
+    end
c99b38
+
c99b38
     # @param env [Hash]
c99b38
     def with_env(env)
c99b38
       backup = ENV.to_hash
c99b38
diff --git a/spec/bundler/bundler/bundler_spec.rb b/spec/bundler/bundler/bundler_spec.rb
c99b38
index 74cf7ae05d3..247838600bf 100644
c99b38
--- a/spec/bundler/bundler/bundler_spec.rb
c99b38
+++ b/spec/bundler/bundler/bundler_spec.rb
c99b38
@@ -232,16 +232,13 @@
c99b38
           path = "/home/oggy"
c99b38
           allow(Bundler.rubygems).to receive(:user_home).and_return(path)
c99b38
           allow(File).to receive(:directory?).with(path).and_return false
c99b38
-          allow(Etc).to receive(:getlogin).and_return("USER")
c99b38
-          allow(Dir).to receive(:tmpdir).and_return("/TMP")
c99b38
-          allow(FileTest).to receive(:exist?).with("/TMP/bundler/home").and_return(true)
c99b38
-          expect(FileUtils).to receive(:mkpath).with("/TMP/bundler/home/USER")
c99b38
+          allow(Bundler).to receive(:tmp).and_return(Pathname.new("/tmp/trulyrandom"))
c99b38
           message = <
c99b38
 `/home/oggy` is not a directory.
c99b38
-Bundler will use `/TMP/bundler/home/USER' as your home directory temporarily.
c99b38
+Bundler will use `/tmp/trulyrandom' as your home directory temporarily.
c99b38
 EOF
c99b38
           expect(Bundler.ui).to receive(:warn).with(message)
c99b38
-          expect(Bundler.user_home).to eq(Pathname("/TMP/bundler/home/USER"))
c99b38
+          expect(Bundler.user_home).to eq(Pathname("/tmp/trulyrandom"))
c99b38
         end
c99b38
       end
c99b38
 
c99b38
@@ -254,16 +251,13 @@
c99b38
           allow(File).to receive(:directory?).with(path).and_return true
c99b38
           allow(File).to receive(:writable?).with(path).and_return false
c99b38
           allow(File).to receive(:directory?).with(dotbundle).and_return false
c99b38
-          allow(Etc).to receive(:getlogin).and_return("USER")
c99b38
-          allow(Dir).to receive(:tmpdir).and_return("/TMP")
c99b38
-          allow(FileTest).to receive(:exist?).with("/TMP/bundler/home").and_return(true)
c99b38
-          expect(FileUtils).to receive(:mkpath).with("/TMP/bundler/home/USER")
c99b38
+          allow(Bundler).to receive(:tmp).and_return(Pathname.new("/tmp/trulyrandom"))
c99b38
           message = <
c99b38
 `/home/oggy` is not writable.
c99b38
-Bundler will use `/TMP/bundler/home/USER' as your home directory temporarily.
c99b38
+Bundler will use `/tmp/trulyrandom' as your home directory temporarily.
c99b38
 EOF
c99b38
           expect(Bundler.ui).to receive(:warn).with(message)
c99b38
-          expect(Bundler.user_home).to eq(Pathname("/TMP/bundler/home/USER"))
c99b38
+          expect(Bundler.user_home).to eq(Pathname("/tmp/trulyrandom"))
c99b38
         end
c99b38
 
c99b38
         context ".bundle exists and have correct permissions" do
c99b38
@@ -282,31 +276,17 @@
c99b38
     context "home directory is not set" do
c99b38
       it "should issue warning and return a temporary user home" do
c99b38
         allow(Bundler.rubygems).to receive(:user_home).and_return(nil)
c99b38
-        allow(Etc).to receive(:getlogin).and_return("USER")
c99b38
-        allow(Dir).to receive(:tmpdir).and_return("/TMP")
c99b38
-        allow(FileTest).to receive(:exist?).with("/TMP/bundler/home").and_return(true)
c99b38
-        expect(FileUtils).to receive(:mkpath).with("/TMP/bundler/home/USER")
c99b38
+        allow(Bundler).to receive(:tmp).and_return(Pathname.new("/tmp/trulyrandom"))
c99b38
         message = <
c99b38
 Your home directory is not set.
c99b38
-Bundler will use `/TMP/bundler/home/USER' as your home directory temporarily.
c99b38
+Bundler will use `/tmp/trulyrandom' as your home directory temporarily.
c99b38
 EOF
c99b38
         expect(Bundler.ui).to receive(:warn).with(message)
c99b38
-        expect(Bundler.user_home).to eq(Pathname("/TMP/bundler/home/USER"))
c99b38
+        expect(Bundler.user_home).to eq(Pathname("/tmp/trulyrandom"))
c99b38
       end
c99b38
     end
c99b38
   end
c99b38
 
c99b38
-  describe "#tmp_home_path" do
c99b38
-    it "should create temporary user home" do
c99b38
-      allow(Dir).to receive(:tmpdir).and_return("/TMP")
c99b38
-      allow(FileTest).to receive(:exist?).with("/TMP/bundler/home").and_return(false)
c99b38
-      expect(FileUtils).to receive(:mkpath).once.ordered.with("/TMP/bundler/home")
c99b38
-      expect(FileUtils).to receive(:mkpath).once.ordered.with("/TMP/bundler/home/USER")
c99b38
-      expect(File).to receive(:chmod).with(0o777, "/TMP/bundler/home")
c99b38
-      expect(Bundler.tmp_home_path("USER", "")).to eq(Pathname("/TMP/bundler/home/USER"))
c99b38
-    end
c99b38
-  end
c99b38
-
c99b38
   describe "#requires_sudo?" do
c99b38
     let!(:tmpdir) { Dir.mktmpdir }
c99b38
     let(:bundle_path) { Pathname("#{tmpdir}/bundle") }
c99b38
diff --git a/spec/bundler/bundler/settings_spec.rb b/spec/bundler/bundler/settings_spec.rb
c99b38
index 7e1dadded76..2a285fdcf37 100644
c99b38
--- a/spec/bundler/bundler/settings_spec.rb
c99b38
+++ b/spec/bundler/bundler/settings_spec.rb
c99b38
@@ -67,7 +67,7 @@
c99b38
       context "when $TMPDIR is not writable" do
c99b38
         it "does not raise" do
c99b38
           expect(Bundler.rubygems).to receive(:user_home).twice.and_return(nil)
c99b38
-          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")
c99b38
+          expect(Bundler).to receive(:tmp).twice.and_raise(Errno::EROFS, "Read-only file system @ dir_s_mkdir - /tmp/bundler")
c99b38
 
c99b38
           expect(subject.send(:global_config_file)).to be_nil
c99b38
         end