Skip to content
This repository was archived by the owner on Apr 19, 2018. It is now read-only.

Commit 5b6ca7b

Browse files
committed
Merge branch 'path_fixes' into 'master'
Path fixes Improve the path handling in Grit to guard against path traversal and accidentally shelling out. See merge request !8
2 parents a7cd2c6 + 4a36e4c commit 5b6ca7b

File tree

4 files changed

+26
-4
lines changed

4 files changed

+26
-4
lines changed

History.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
== 2.7.3
2+
* Add guards against path traversal and leading '|'
3+
14
== 2.7.2
25
* Make sure grit restores old timeout value even if exception occures
36

lib/grit/git-ruby/repository.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -683,7 +683,9 @@ def self.create_initial_config(bare = false)
683683
end
684684

685685
def self.add_file(name, contents)
686-
File.open(name, 'w') do |f|
686+
path = File.join(Dir.pwd, name)
687+
raise "Invalid path: #{path}" unless File.absolute_path(path) == path
688+
File.open(path, 'w') do |f|
687689
f.write contents
688690
end
689691
end

lib/grit/git.rb

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,15 +117,19 @@ def shell_escape(str)
117117
#
118118
# Returns Boolean
119119
def fs_exist?(file)
120-
File.exist?(File.join(self.git_dir, file))
120+
path = File.join(self.git_dir, file)
121+
raise "Invalid path: #{path}" unless File.absolute_path(path) == path
122+
File.exist?(path)
121123
end
122124

123125
# Read a normal file from the filesystem.
124126
# +file+ is the relative path from the Git dir
125127
#
126128
# Returns the String contents of the file
127129
def fs_read(file)
128-
File.read(File.join(self.git_dir, file))
130+
path = File.join(self.git_dir, file)
131+
raise "Invalid path: #{path}" unless File.absolute_path(path) == path
132+
File.read(path)
129133
end
130134

131135
# Write a normal file to the filesystem.
@@ -135,6 +139,7 @@ def fs_read(file)
135139
# Returns nothing
136140
def fs_write(file, contents)
137141
path = File.join(self.git_dir, file)
142+
raise "Invalid path: #{path}" unless File.absolute_path(path) == path
138143
FileUtils.mkdir_p(File.dirname(path))
139144
File.open(path, 'w') do |f|
140145
f.write(contents)

test/test_git.rb

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
class TestGit < Test::Unit::TestCase
44
def setup
5-
@git = Git.new(File.join(File.dirname(__FILE__), *%w[..]))
5+
@git = Git.new(File.absolute_path(File.join(File.dirname(__FILE__), *%w[..])))
66
end
77

88
def teardown
@@ -83,6 +83,12 @@ def test_fs_read
8383
assert_equal 'bar', @git.fs_read('foo')
8484
end
8585

86+
def test_fs_read_path_traversal
87+
assert_raise RuntimeError do
88+
@git.fs_read('../foo')
89+
end
90+
end
91+
8692
def test_fs_write
8793
f = stub
8894
f.expects(:write).with('baz')
@@ -91,6 +97,12 @@ def test_fs_write
9197
@git.fs_write('foo/bar', 'baz')
9298
end
9399

100+
def test_fs_write_path_traversal
101+
assert_raise RuntimeError do
102+
@git.fs_read('../foo/bar')
103+
end
104+
end
105+
94106
def test_fs_delete
95107
FileUtils.expects(:rm_rf).with(File.join(@git.git_dir, 'foo'))
96108
@git.fs_delete('foo')

0 commit comments

Comments
 (0)