Skip to content

Commit

Permalink
Implement a safe mkdir for package that verifies were inside the dest…
Browse files Browse the repository at this point in the history
…ination dir for all new directories ccreated
  • Loading branch information
segiddins committed Feb 16, 2018
1 parent a67d9f6 commit 666ef79
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 6 deletions.
33 changes: 28 additions & 5 deletions lib/rubygems/package.rb
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@ def extract_tar_gz io, destination_dir, pattern = "*" # :nodoc:
File.dirname destination
end

FileUtils.mkdir_p mkdir, mkdir_options
mkdir_p_safe mkdir, mkdir_options, destination_dir, entry.full_name

File.open destination, 'wb' do |out|
out.write entry.read
Expand Down Expand Up @@ -416,13 +416,10 @@ def install_location filename, destination_dir # :nodoc:
raise Gem::Package::PathError.new(filename, destination_dir) if
filename.start_with? '/'

destination_dir = File.realpath destination_dir if
File.respond_to? :realpath
destination_dir = realpath destination_dir
destination_dir = File.expand_path destination_dir

destination = File.join destination_dir, filename
destination = File.realpath destination if
File.respond_to? :realpath
destination = File.expand_path destination

raise Gem::Package::PathError.new(destination, destination_dir) unless
Expand All @@ -432,6 +429,22 @@ def install_location filename, destination_dir # :nodoc:
destination
end

def mkdir_p_safe mkdir, mkdir_options, destination_dir, file_name
destination_dir = realpath File.expand_path(destination_dir)
parts = mkdir.split(File::SEPARATOR)
parts.reduce do |path, basename|
path = realpath path unless path == ""
path = File.expand_path(path + File::SEPARATOR + basename)
lstat = File.lstat path rescue nil
if !lstat || !lstat.directory?
unless path.start_with? destination_dir and (FileUtils.mkdir path, mkdir_options rescue false)
raise Gem::Package::PathError.new(file_name, destination_dir)
end
end
path
end
end

##
# Loads a Gem::Specification from the TarEntry +entry+

Expand Down Expand Up @@ -622,6 +635,16 @@ def verify_gz entry # :nodoc:
raise Gem::Package::FormatError.new(e.message, entry.full_name)
end

if File.respond_to? :realpath
def realpath file
File.realpath file
end
else
def realpath file
file
end
end

end

require 'rubygems/package/digest_io'
Expand Down
2 changes: 1 addition & 1 deletion test/rubygems/test_gem_package.rb
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,7 @@ def test_extract_symlink_parent
package.extract_tar_gz tgz_io, destination_subdir
end

assert_equal("installing into parent path ../outside.txt of " +
assert_equal("installing into parent path lib/link/outside.txt of " +
"#{destination_subdir} is not allowed", e.message)
end

Expand Down

0 comments on commit 666ef79

Please sign in to comment.