Description: strip absolute paths more comprehensively Author: isaacs <i@izs.me> Origin: upstream, https://github.com/npm/node-tar/commit/1f036ca2 Bug: https://github.com/npm/node-tar/security/advisories/GHSA-3jfq-g458-7qm9 Bug-Debian: https://bugs.debian.org/992111 Forwarded: not-needed Reviewed-By: Yadd <yadd@debian.org> Last-Update: 2021-08-11 --- /dev/null +++ b/lib/strip-absolute-path.js @@ -0,0 +1,14 @@ +// unix absolute paths are also absolute on win32, so we use this for both +const { isAbsolute, parse } = require('path').win32 + +// returns [root, stripped] +module.exports = path => { + let r = '' + while (isAbsolute(path)) { + // windows will think that //x/y/z has a "root" of //x/y/ + const root = path.charAt(0) === '/' ? '/' : parse(path).root + path = path.substr(root.length) + r += root + } + return [r, path] +} --- a/lib/unpack.js +++ b/lib/unpack.js @@ -16,6 +16,7 @@ const mkdirSync = mkdir.sync const wc = require('./winchars.js') const pathReservations = require('./path-reservations.js') +const stripAbsolutePath = require('./strip-absolute-path.js') const ONENTRY = Symbol('onEntry') const CHECKFS = Symbol('checkFs') @@ -223,11 +224,10 @@ // absolutes on posix are also absolutes on win32 // so we only need to test this one to get both - if (path.win32.isAbsolute(p)) { - const parsed = path.win32.parse(p) - entry.path = p.substr(parsed.root.length) - const r = parsed.root - this.warn('TAR_ENTRY_INFO', `stripping ${r} from absolute path`, { + const [root, stripped] = stripAbsolutePath(p) + if (root) { + entry.path = stripped + this.warn('TAR_ENTRY_INFO', `stripping ${root} from absolute path`, { entry, path: p, }) --- a/lib/write-entry.js +++ b/lib/write-entry.js @@ -25,6 +25,7 @@ const MODE = Symbol('mode') const warner = require('./warn-mixin.js') const winchars = require('./winchars.js') +const stripAbsolutePath = require('./strip-absolute-path.js') const modeFix = require('./mode-fix.js') @@ -54,12 +55,12 @@ this.on('warn', opt.onwarn) let pathWarn = false - if (!this.preservePaths && path.win32.isAbsolute(p)) { - // absolutes on posix are also absolutes on win32 - // so we only need to test this one to get both - const parsed = path.win32.parse(p) - this.path = p.substr(parsed.root.length) - pathWarn = parsed.root + if (!this.preservePaths) { + const [root, stripped] = stripAbsolutePath(this.path) + if (root) { + this.path = stripped + pathWarn = root + } } this.win32 = !!opt.win32 || process.platform === 'win32' @@ -353,10 +354,12 @@ this.on('warn', opt.onwarn) let pathWarn = false - if (path.isAbsolute(this.path) && !this.preservePaths) { - const parsed = path.parse(this.path) - pathWarn = parsed.root - this.path = this.path.substr(parsed.root.length) + if (!this.preservePaths) { + const [root, stripped] = stripAbsolutePath(this.path) + if (root) { + this.path = stripped + pathWarn = root + } } this.remain = readEntry.size