@@ -33,6 +33,7 @@ const SYMLINK = Symbol('symlink')
3333const HARDLINK = Symbol ( 'hardlink' )
3434const UNSUPPORTED = Symbol ( 'unsupported' )
3535const CHECKPATH = Symbol ( 'checkPath' )
36+ const STRIPABSOLUTEPATH = Symbol ( 'stripAbsolutePath' )
3637const MKDIR = Symbol ( 'mkdir' )
3738const ONERROR = Symbol ( 'onError' )
3839const PENDING = Symbol ( 'pending' )
@@ -263,6 +264,46 @@ export class Unpack extends Parser {
263264 }
264265 }
265266
267+ // return false if we need to skip this file
268+ // return true if the field was successfully sanitized
269+ [ STRIPABSOLUTEPATH ] (
270+ entry : ReadEntry ,
271+ field : 'path' | 'linkpath' ,
272+ ) : boolean {
273+ const path = entry [ field ]
274+ if ( ! path || this . preservePaths ) return true
275+
276+ const parts = path . split ( '/' )
277+ if (
278+ parts . includes ( '..' ) ||
279+ /* c8 ignore next */
280+ ( isWindows && / ^ [ a - z ] : \. \. $ / i. test ( parts [ 0 ] ?? '' ) )
281+ ) {
282+ this . warn ( 'TAR_ENTRY_ERROR' , `${ field } contains '..'` , {
283+ entry,
284+ [ field ] : path ,
285+ } )
286+ // not ok!
287+ return false
288+ }
289+
290+ // strip off the root
291+ const [ root , stripped ] = stripAbsolutePath ( path )
292+ if ( root ) {
293+ // ok, but triggers warning about stripping root
294+ entry [ field ] = String ( stripped )
295+ this . warn (
296+ 'TAR_ENTRY_INFO' ,
297+ `stripping ${ root } from absolute ${ field } ` ,
298+ {
299+ entry,
300+ [ field ] : path ,
301+ } ,
302+ )
303+ }
304+ return true
305+ }
306+
266307 [ CHECKPATH ] ( entry : ReadEntry ) {
267308 const p = normalizeWindowsPath ( entry . path )
268309 const parts = p . split ( '/' )
@@ -295,32 +336,11 @@ export class Unpack extends Parser {
295336 return false
296337 }
297338
298- if ( ! this . preservePaths ) {
299- if (
300- parts . includes ( '..' ) ||
301- /* c8 ignore next */
302- ( isWindows && / ^ [ a - z ] : \. \. $ / i. test ( parts [ 0 ] ?? '' ) )
303- ) {
304- this . warn ( 'TAR_ENTRY_ERROR' , `path contains '..'` , {
305- entry,
306- path : p ,
307- } )
308- return false
309- }
310-
311- // strip off the root
312- const [ root , stripped ] = stripAbsolutePath ( p )
313- if ( root ) {
314- entry . path = String ( stripped )
315- this . warn (
316- 'TAR_ENTRY_INFO' ,
317- `stripping ${ root } from absolute path` ,
318- {
319- entry,
320- path : p ,
321- } ,
322- )
323- }
339+ if (
340+ ! this [ STRIPABSOLUTEPATH ] ( entry , 'path' ) ||
341+ ! this [ STRIPABSOLUTEPATH ] ( entry , 'linkpath' )
342+ ) {
343+ return false
324344 }
325345
326346 if ( path . isAbsolute ( entry . path ) ) {
0 commit comments