@@ -11,6 +11,14 @@ import { Header, x } from 'tar'
1111const targetSym = '/some/absolute/path'
1212const absoluteWithDotDot = '/../a/target'
1313
14+ const secretLinkpath = resolve ( t . testdirName , 'secret.txt' )
15+
16+ t . formatSnapshot = ( o : unknown ) : unknown =>
17+ typeof o === 'string' ? o . replace (
18+ / ^ E N O E N T : n o s u c h f i l e o r d i r e c t o r y , l i n k .* ? - > .* ?$ / , 'ENOENT: no such file or directory, link' )
19+ : Array . isArray ( o ) ? o . map ( o => t . formatSnapshot ?.( o ) )
20+ : o
21+
1422const getExploitTar = ( ) => {
1523 const chunks : Buffer [ ] = [ ]
1624
@@ -19,7 +27,7 @@ const getExploitTar = () => {
1927 path : 'exploit_hard' ,
2028 type : 'Link' ,
2129 size : 0 ,
22- linkpath : resolve ( t . testdirName , 'secret.txt' ) ,
30+ linkpath : secretLinkpath ,
2331 } ) . encode ( hardHeader , 0 )
2432 chunks . push ( hardHeader )
2533
@@ -78,6 +86,14 @@ const getExploitTar = () => {
7886 } ) . encode ( winAbsWithDotDotHeader , 0 )
7987 chunks . push ( winAbsWithDotDotHeader )
8088
89+ const winAbsWithDotDotEscapeHeader = Buffer . alloc ( 512 )
90+ new Header ( {
91+ path : 'a/winrootdotsescapelink' ,
92+ type : 'SymbolicLink' ,
93+ linkpath : 'c:..\\..\\..\\..\\foo\\bar' ,
94+ } ) . encode ( winAbsWithDotDotEscapeHeader , 0 )
95+ chunks . push ( winAbsWithDotDotEscapeHeader )
96+
8197 chunks . push ( Buffer . alloc ( 1024 ) )
8298 return Buffer . concat ( chunks )
8399}
@@ -91,7 +107,17 @@ const dir = t.testdir({
91107const out = resolve ( dir , 'out' )
92108const tarFile = resolve ( dir , 'exploit.tar' )
93109
94- t . before ( ( ) => x ( { cwd : out , file : tarFile } ) )
110+ const WARNINGS : [ code : string , message : string ] [ ] = [ ]
111+ t . before ( ( ) =>
112+ x ( {
113+ cwd : out ,
114+ file : tarFile ,
115+ onwarn : ( code : string , message : string ) =>
116+ WARNINGS . push ( [ code , message ] ) ,
117+ } ) ,
118+ )
119+
120+ t . test ( 'warnings' , async t => t . matchSnapshot ( WARNINGS ) )
95121
96122t . test ( 'writefile exploits fail' , async t => {
97123 writeFileSync ( resolve ( out , 'exploit_hard' ) , 'OVERWRITTEN' )
@@ -126,4 +152,8 @@ t.test('absolute symlink with .. has prefix stripped', async t => {
126152 '..\\foo\\bar' ,
127153 'symlink target should be normalized' ,
128154 )
155+ t . throws (
156+ ( ) => lstatSync ( resolve ( out , 'a/winrootdotsescapelink' ) ) ,
157+ 'escaping symlink is not created' ,
158+ )
129159} )
0 commit comments