File: path_traversal_test.rb

package info (click to toggle)
ruby-zip 1.2.2-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 1,036 kB
  • sloc: ruby: 7,760; makefile: 18
file content (134 lines) | stat: -rw-r--r-- 3,514 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
class PathTraversalTest < MiniTest::Test
  TEST_FILE_ROOT = File.absolute_path('test/data/path_traversal')

  def setup
    # With apologies to anyone using these files... but they are the files in
    # the sample zips, so we don't have much choice here.
    FileUtils.rm_f '/tmp/moo'
    FileUtils.rm_f '/tmp/file.txt'
  end

  def extract_path_traversal_zip(name)
    Zip::File.open(File.join(TEST_FILE_ROOT, name)) do |zip_file|
      zip_file.each do |entry|
        entry.extract
      end
    end
  end

  def in_tmpdir
    Dir.mktmpdir do |tmp|
      test_path = File.join(tmp, 'test')
      Dir.mkdir test_path
      Dir.chdir test_path do
        yield test_path
      end
    end
  end

  def test_leading_slash
    in_tmpdir do
      extract_path_traversal_zip 'jwilk/absolute1.zip'
      refute File.exist?('/tmp/moo')
    end
  end

  def test_multiple_leading_slashes
    in_tmpdir do
      extract_path_traversal_zip 'jwilk/absolute2.zip'
      refute File.exist?('/tmp/moo')
    end
  end

  def test_leading_dot_dot
    in_tmpdir do
      extract_path_traversal_zip 'jwilk/relative0.zip'
      refute File.exist?('../moo')
    end
  end

  def test_non_leading_dot_dot_with_existing_folder
    in_tmpdir do
      extract_path_traversal_zip 'relative1.zip'
      assert Dir.exist?('tmp')
      refute File.exist?('../moo')
    end
  end

  def test_non_leading_dot_dot_without_existing_folder
    in_tmpdir do
      extract_path_traversal_zip 'jwilk/relative2.zip'
      refute File.exist?('../moo')
    end
  end

  def test_file_symlink
    in_tmpdir do
      extract_path_traversal_zip 'jwilk/symlink.zip'
      assert File.exist?('moo')
      refute File.exist?('/tmp/moo')
    end
  end

  def test_directory_symlink
    in_tmpdir do
      # Can't create tmp/moo, because the tmp symlink is skipped.
      assert_raises Errno::ENOENT do
        extract_path_traversal_zip 'jwilk/dirsymlink.zip'
      end
      refute File.exist?('/tmp/moo')
    end
  end

  def test_two_directory_symlinks_a
    in_tmpdir do
      # Can't create par/moo because the symlinks are skipped.
      assert_raises Errno::ENOENT do
        extract_path_traversal_zip 'jwilk/dirsymlink2a.zip'
      end
      refute File.exist?('cur')
      refute File.exist?('par')
      refute File.exist?('par/moo')
    end
  end

  def test_two_directory_symlinks_b
    in_tmpdir do
      # Can't create par/moo, because the symlinks are skipped.
      assert_raises Errno::ENOENT do
        extract_path_traversal_zip 'jwilk/dirsymlink2b.zip'
      end
      refute File.exist?('cur')
      refute File.exist?('../moo')
    end
  end

  def test_entry_name_with_absolute_path_does_not_extract
    in_tmpdir do
      extract_path_traversal_zip 'tuzovakaoff/absolutepath.zip'
      refute File.exist?('/tmp/file.txt')
    end
  end

  def test_entry_name_with_absolute_path_extract_when_given_different_path
    in_tmpdir do |test_path|
      zip_path = File.join(TEST_FILE_ROOT, 'tuzovakaoff/absolutepath.zip')
      Zip::File.open(zip_path) do |zip_file|
        zip_file.each do |entry|
          entry.extract(File.join(test_path, entry.name))
        end
      end
      refute File.exist?('/tmp/file.txt')
    end
  end

  def test_entry_name_with_relative_symlink
    in_tmpdir do
      # Doesn't create the symlink path, so can't create path/file.txt.
      assert_raises Errno::ENOENT do
        extract_path_traversal_zip 'tuzovakaoff/symlink.zip'
      end
      refute File.exist?('/tmp/file.txt')
    end
  end
end