Skip to content
This repository has been archived by the owner on Apr 14, 2021. It is now read-only.

Commit

Permalink
Don't use insecure temporary directory as home directory
Browse files Browse the repository at this point in the history
  • Loading branch information
fatkodima committed Nov 4, 2019
1 parent 674966e commit 65cfebb
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 47 deletions.
29 changes: 12 additions & 17 deletions lib/bundler.rb
Expand Up @@ -167,8 +167,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
Expand All @@ -177,21 +176,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"
Expand Down Expand Up @@ -612,6 +596,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
Expand Down
38 changes: 9 additions & 29 deletions spec/bundler/bundler_spec.rb
Expand Up @@ -232,16 +232,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

Expand All @@ -254,16 +251,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
Expand All @@ -282,31 +276,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") }
Expand Down
2 changes: 1 addition & 1 deletion spec/bundler/settings_spec.rb
Expand Up @@ -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
Expand Down

0 comments on commit 65cfebb

Please sign in to comment.