@@ -3,10 +3,22 @@ import path from 'path';
3
3
import isJpg from 'is-jpg' ;
4
4
import pathExists from 'path-exists' ;
5
5
import pify from 'pify' ;
6
+ import rimraf from 'rimraf' ;
6
7
import test from 'ava' ;
7
8
import m from '.' ;
8
9
9
10
const fsP = pify ( fs ) ;
11
+ const rimrafP = pify ( rimraf ) ;
12
+
13
+ test . serial . afterEach ( 'ensure decompressed files and directories are cleaned up' , async ( ) => {
14
+ await rimrafP ( path . join ( __dirname , 'directory' ) ) ;
15
+ await rimrafP ( path . join ( __dirname , 'dist' ) ) ;
16
+ await rimrafP ( path . join ( __dirname , 'example.txt' ) ) ;
17
+ await rimrafP ( path . join ( __dirname , 'file.txt' ) ) ;
18
+ await rimrafP ( path . join ( __dirname , 'edge_case_dots' ) ) ;
19
+ await rimrafP ( path . join ( __dirname , 'symlink' ) ) ;
20
+ await rimrafP ( path . join ( __dirname , 'test.jpg' ) ) ;
21
+ } ) ;
10
22
11
23
test ( 'extract file' , async t => {
12
24
const tarFiles = await m ( path . join ( __dirname , 'fixtures' , 'file.tar' ) ) ;
@@ -46,21 +58,16 @@ test.serial('extract file to directory', async t => {
46
58
t . is ( files [ 0 ] . path , 'test.jpg' ) ;
47
59
t . true ( isJpg ( files [ 0 ] . data ) ) ;
48
60
t . true ( await pathExists ( path . join ( __dirname , 'test.jpg' ) ) ) ;
49
-
50
- await fsP . unlink ( path . join ( __dirname , 'test.jpg' ) ) ;
51
61
} ) ;
52
62
53
- test ( 'extract symlink' , async t => {
63
+ test . serial ( 'extract symlink' , async t => {
54
64
await m ( path . join ( __dirname , 'fixtures' , 'symlink.tar' ) , __dirname , { strip : 1 } ) ;
55
65
t . is ( await fsP . realpath ( path . join ( __dirname , 'symlink' ) ) , path . join ( __dirname , 'file.txt' ) ) ;
56
- await fsP . unlink ( path . join ( __dirname , 'symlink' ) ) ;
57
- await fsP . unlink ( path . join ( __dirname , 'file.txt' ) ) ;
58
66
} ) ;
59
67
60
- test ( 'extract directory' , async t => {
68
+ test . serial ( 'extract directory' , async t => {
61
69
await m ( path . join ( __dirname , 'fixtures' , 'directory.tar' ) , __dirname ) ;
62
70
t . true ( await pathExists ( path . join ( __dirname , 'directory' ) ) ) ;
63
- await fsP . rmdir ( path . join ( __dirname , 'directory' ) ) ;
64
71
} ) ;
65
72
66
73
test ( 'strip option' , async t => {
@@ -96,10 +103,58 @@ test.serial('set mtime', async t => {
96
103
const files = await m ( path . join ( __dirname , 'fixtures' , 'file.tar' ) , __dirname ) ;
97
104
const stat = await fsP . stat ( path . join ( __dirname , 'test.jpg' ) ) ;
98
105
t . deepEqual ( files [ 0 ] . mtime , stat . mtime ) ;
99
- await fsP . unlink ( path . join ( __dirname , 'test.jpg' ) ) ;
100
106
} ) ;
101
107
102
108
test ( 'return emptpy array if no plugins are set' , async t => {
103
109
const files = await m ( path . join ( __dirname , 'fixtures' , 'file.tar' ) , { plugins : [ ] } ) ;
104
110
t . is ( files . length , 0 ) ;
105
111
} ) ;
112
+
113
+ test . serial ( 'throw when a location outside the root is given' , async t => {
114
+ await t . throwsAsync ( async ( ) => {
115
+ await m ( path . join ( __dirname , 'fixtures' , 'slipping.tar.gz' ) , 'dist' ) ;
116
+ } , { message : / R e f u s i n g / } ) ;
117
+ } ) ;
118
+
119
+ test . serial ( 'throw when a location outside the root including symlinks is given' , async t => {
120
+ await t . throwsAsync ( async ( ) => {
121
+ await m ( path . join ( __dirname , 'fixtures' , 'slip.zip' ) , 'dist' ) ;
122
+ } , { message : / R e f u s i n g / } ) ;
123
+ } ) ;
124
+
125
+ test . serial ( 'throw when a top-level symlink outside the root is given' , async t => {
126
+ await t . throwsAsync ( async ( ) => {
127
+ await m ( path . join ( __dirname , 'fixtures' , 'slip2.zip' ) , 'dist' ) ;
128
+ } , { message : / R e f u s i n g / } ) ;
129
+ } ) ;
130
+
131
+ test . serial ( 'throw when a directory outside the root including symlinks is given' , async t => {
132
+ await t . throwsAsync ( async ( ) => {
133
+ await m ( path . join ( __dirname , 'fixtures' , 'slipping_directory.tar.gz' ) , 'dist' ) ;
134
+ } , { message : / R e f u s i n g / } ) ;
135
+ } ) ;
136
+
137
+ test . serial ( 'allows filenames and directories to be written with dots in their names' , async t => {
138
+ const files = await m ( path . join ( __dirname , 'fixtures' , 'edge_case_dots.tar.gz' ) , __dirname ) ;
139
+ t . is ( files . length , 6 ) ;
140
+ t . deepEqual ( files . map ( f => f . path ) . sort ( ) , [
141
+ 'edge_case_dots/' ,
142
+ 'edge_case_dots/internal_dots..txt' ,
143
+ 'edge_case_dots/sample../' ,
144
+ 'edge_case_dots/ending_dots..' ,
145
+ 'edge_case_dots/x' ,
146
+ 'edge_case_dots/sample../test.txt'
147
+ ] . sort ( ) ) ;
148
+ } ) ;
149
+
150
+ test . serial ( 'allows top-level file' , async t => {
151
+ const files = await m ( path . join ( __dirname , 'fixtures' , 'top_level_example.tar.gz' ) , 'dist' ) ;
152
+ t . is ( files . length , 1 ) ;
153
+ t . is ( files [ 0 ] . path , 'example.txt' ) ;
154
+ } ) ;
155
+
156
+ test . serial ( 'throw when chained symlinks to /tmp/dist allow escape outside root directory' , async t => {
157
+ await t . throwsAsync ( async ( ) => {
158
+ await m ( path . join ( __dirname , 'fixtures' , 'slip3.zip' ) , '/tmp/dist' ) ;
159
+ } , { message : / R e f u s i n g / } ) ;
160
+ } ) ;
0 commit comments