Socket
Socket
Sign inDemoInstall

tar

Package Overview
Dependencies
7
Maintainers
7
Versions
123
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 5.0.9 to 5.0.10

31

lib/path-reservations.js

@@ -11,4 +11,8 @@ // A path exclusive reservation system

const normPath = require('./normalize-windows-path.js')
const stripSlashes = require('./strip-trailing-slashes.js')
const { join } = require('path')
const platform = process.env.TESTING_TAR_FAKE_PLATFORM || process.platform
const isWindows = platform === 'win32'
module.exports = () => {

@@ -24,6 +28,12 @@ // path => [function or Set]

// return a set of parent dirs for a given path
const getDirs = path =>
path.split('/').slice(0, -1).reduce((set, path) =>
set.length ? set.concat(normPath(join(set[set.length - 1], path)))
: [path], [])
// '/a/b/c/d' -> ['/', '/a', '/a/b', '/a/b/c', '/a/b/c/d']
const getDirs = path => {
const dirs = path.split('/').slice(0, -1).reduce((set, path) => {
if (set.length)
path = normPath(join(set[set.length - 1], path))
set.push(path || '/')
return set
}, [])
return dirs
}

@@ -104,3 +114,14 @@ // functions currently running

const reserve = (paths, fn) => {
paths = paths.map(p => normPath(join(p)).toLowerCase())
// collide on matches across case and unicode normalization
// On windows, thanks to the magic of 8.3 shortnames, it is fundamentally
// impossible to determine whether two paths refer to the same thing on
// disk, without asking the kernel for a shortname.
// So, we just pretend that every path matches every other path here,
// effectively removing all parallelization on windows.
paths = isWindows ? ['win32 parallelization disabled'] : paths.map(p => {
return stripSlashes(normPath(join(p)))
.normalize('NFKD')
.toLowerCase()
})
const dirs = new Set(

@@ -107,0 +128,0 @@ paths.map(path => getDirs(path)).reduce((a, b) => a.concat(b))

@@ -5,11 +5,21 @@ // unix absolute paths are also absolute on win32, so we use this for both

// returns [root, stripped]
// Note that windows will think that //x/y/z/a has a "root" of //x/y, and in
// those cases, we want to sanitize it to x/y/z/a, not z/a, so we strip /
// explicitly if it's the first character.
// drive-specific relative paths on Windows get their root stripped off even
// though they are not absolute, so `c:../foo` becomes ['c:', '../foo']
module.exports = path => {
let r = ''
while (isAbsolute(path)) {
let parsed = parse(path)
while (isAbsolute(path) || parsed.root) {
// windows will think that //x/y/z has a "root" of //x/y/
const root = path.charAt(0) === '/' ? '/' : parse(path).root
// but strip the //?/C:/ off of //?/C:/path
const root = path.charAt(0) === '/' && path.slice(0, 4) !== '//?/' ? '/'
: parsed.root
path = path.substr(root.length)
r += root
parsed = parse(path)
}
return [r, path]
}

109

lib/unpack.js

@@ -21,2 +21,3 @@ 'use strict'

const normPath = require('./normalize-windows-path.js')
const stripSlash = require('./strip-trailing-slashes.js')

@@ -26,2 +27,3 @@ const ONENTRY = Symbol('onEntry')

const CHECKFS2 = Symbol('checkFs2')
const PRUNECACHE = Symbol('pruneCache')
const ISREUSABLE = Symbol('isReusable')

@@ -51,2 +53,4 @@ const MAKEFS = Symbol('makeFs')

const getFlag = require('./get-write-flag.js')
const platform = process.env.TESTING_TAR_FAKE_PLATFORM || process.platform
const isWindows = platform === 'win32'

@@ -70,3 +74,3 @@ // Unlinks on Windows are not atomic.

const unlinkFile = (path, cb) => {
if (process.platform !== 'win32')
if (!isWindows)
return fs.unlink(path, cb)

@@ -84,3 +88,3 @@

const unlinkFileSync = path => {
if (process.platform !== 'win32')
if (!isWindows)
return fs.unlinkSync(path)

@@ -99,9 +103,20 @@

// clear the cache if it's a case-insensitive unicode-squashing match.
// we can't know if the current file system is case-sensitive or supports
// unicode fully, so we check for similarity on the maximally compatible
// representation. Err on the side of pruning, since all it's doing is
// preventing lstats, and it's not the end of the world if we get a false
// positive.
// Note that on windows, we always drop the entire cache whenever a
// symbolic link is encountered, because 8.3 filenames are impossible
// to reason about, and collisions are hazards rather than just failures.
const cacheKeyNormalize = path => stripSlash(normPath(path))
.normalize('NFKD')
.toLowerCase()
const pruneCache = (cache, abs) => {
// clear the cache if it's a case-insensitive match, since we can't
// know if the current file system is case-sensitive or not.
abs = normPath(abs).toLowerCase()
abs = cacheKeyNormalize(abs)
for (const path of cache.keys()) {
const plower = path.toLowerCase()
if (plower === abs || plower.toLowerCase().indexOf(abs + '/') === 0)
const pnorm = cacheKeyNormalize(path)
if (pnorm === abs || pnorm.indexOf(abs + '/') === 0)
cache.delete(path)

@@ -111,2 +126,7 @@ }

const dropCache = cache => {
for (const key of cache.keys())
cache.delete(key)
}
class Unpack extends Parser {

@@ -170,3 +190,3 @@ constructor (opt) {

// turn ><?| in filenames into 0xf000-higher encoded forms
this.win32 = !!opt.win32 || process.platform === 'win32'
this.win32 = !!opt.win32 || isWindows

@@ -237,3 +257,4 @@ // do not unpack over files that are newer than what's in the archive

const p = normPath(entry.path)
if (p.split('/').includes('..')) {
const parts = p.split('/')
if (parts.includes('..') || isWindows && /^[a-z]:\.\.$/i.test(parts[0])) {
this.warn('TAR_ENTRY_ERROR', `path contains '..'`, {

@@ -246,4 +267,3 @@ entry,

// absolutes on posix are also absolutes on win32
// so we only need to test this one to get both
// strip off the root
const [root, stripped] = stripAbsolutePath(p)

@@ -264,2 +284,18 @@ if (root) {

// if we somehow ended up with a path that escapes the cwd, and we are
// not in preservePaths mode, then something is fishy! This should have
// been prevented above, so ignore this for coverage.
/* istanbul ignore if - defense in depth */
if (!this.preservePaths &&
entry.absolute.indexOf(this.cwd + '/') !== 0 &&
entry.absolute !== this.cwd) {
this.warn('TAR_ENTRY_ERROR', 'path escaped extraction target', {
entry,
path: normPath(entry.path),
resolvedPath: entry.absolute,
cwd: this.cwd,
})
return false
}
// an archive can set properties on the extraction directory, but it

@@ -508,3 +544,3 @@ // may not replace the cwd with a different kind of thing entirely.

st.nlink <= 1 &&
process.platform !== 'win32'
!isWindows
}

@@ -520,3 +556,4 @@

}
[CHECKFS2] (entry, done) {
[PRUNECACHE] (entry) {
// if we are not creating a directory, and the path is in the dirCache,

@@ -526,5 +563,22 @@ // then that means we are about to delete the directory we created

// is any of its children.
if (entry.type !== 'Directory')
// If a symbolic link is encountered on Windows, all bets are off.
// There is no reasonable way to sanitize the cache in such a way
// we will be able to avoid having filesystem collisions. If this
// happens with a non-symlink entry, it'll just fail to unpack,
// but a symlink to a directory, using an 8.3 shortname, can evade
// detection and lead to arbitrary writes to anywhere on the system.
if (isWindows && entry.type === 'SymbolicLink')
dropCache(this.dirCache)
else if (entry.type !== 'Directory')
pruneCache(this.dirCache, entry.absolute)
}
[CHECKFS2] (entry, fullyDone) {
this[PRUNECACHE](entry)
const done = er => {
this[PRUNECACHE](entry)
fullyDone(er)
}
const checkCwd = () => {

@@ -579,3 +633,9 @@ this[MKDIR](this.cwd, this.dmode, er => {

}
// not a dir entry, have to remove it.
// Not a dir entry, have to remove it.
// NB: the only way to end up with an entry that is the cwd
// itself, in such a way that == does not detect, is a
// tricky windows absolute path with UNC or 8.3 parts (and
// preservePaths:true, or else it will have been stripped).
// In that case, the user has opted out of path protections
// explicitly, so if they blow away the cwd, c'est la vie.
if (entry.absolute !== this.cwd) {

@@ -655,4 +715,3 @@ return fs.rmdir(entry.absolute, er =>

[CHECKFS] (entry) {
if (entry.type !== 'Directory')
pruneCache(this.dirCache, entry.absolute)
this[PRUNECACHE](entry)

@@ -706,3 +765,3 @@ if (!this[CHECKED_CWD]) {

[FILE] (entry, _) {
[FILE] (entry, done) {
const mode = entry.mode & 0o7777 || this.fmode

@@ -719,2 +778,3 @@

this[ONERROR](er || closeError, entry)
done()
}

@@ -780,7 +840,10 @@

[DIRECTORY] (entry, _) {
[DIRECTORY] (entry, done) {
const mode = entry.mode & 0o7777 || this.dmode
const er = this[MKDIR](entry.absolute, mode)
if (er)
return this[ONERROR](er, entry)
if (er) {
this[ONERROR](er, entry)
done()
return
}
if (entry.mtime && !this.noMtime) {

@@ -796,2 +859,3 @@ try {

}
done()
entry.resume()

@@ -819,5 +883,6 @@ }

[LINK] (entry, linkpath, link, _) {
[LINK] (entry, linkpath, link, done) {
try {
fs[link + 'Sync'](linkpath, entry.absolute)
done()
entry.resume()

@@ -824,0 +889,0 @@ } catch (er) {

@@ -5,3 +5,3 @@ {

"description": "tar for node",
"version": "5.0.9",
"version": "5.0.10",
"publishConfig": {

@@ -8,0 +8,0 @@ "tag": "v5-legacy"

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc