Version in base suite: 6.0.5+ds1+~cs11.3.9-1+deb11u1 Base version: node-tar_6.0.5+ds1+~cs11.3.9-1+deb11u1 Target version: node-tar_6.0.5+ds1+~cs11.3.9-1+deb11u2 Base file: /srv/ftp-master.debian.org/ftp/pool/main/n/node-tar/node-tar_6.0.5+ds1+~cs11.3.9-1+deb11u1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/n/node-tar/node-tar_6.0.5+ds1+~cs11.3.9-1+deb11u2.dsc changelog | 11 + patches/CVE-2021-37701.patch | 419 +++++++++++++++++++++++++++++++++++++++ patches/CVE-2021-37712.patch | 90 ++++++++ patches/add-noChmod-option.patch | 109 ++++++++++ patches/series | 3 tests/control | 3 tests/modes | 21 + 7 files changed, 656 insertions(+) diff: /srv/release.debian.org/tmp/4jCITvy_hi/node-tar-6.0.5+ds1+~cs11.3.9/test/fixtures/files/strip-dir/symlink: No such file or directory diff: /srv/release.debian.org/tmp/Odnme2iCQI/node-tar-6.0.5+ds1+~cs11.3.9/test/fixtures/files/strip-dir/symlink: No such file or directory diff -Nru node-tar-6.0.5+ds1+~cs11.3.9/debian/changelog node-tar-6.0.5+ds1+~cs11.3.9/debian/changelog --- node-tar-6.0.5+ds1+~cs11.3.9/debian/changelog 2021-08-11 19:50:15.000000000 +0000 +++ node-tar-6.0.5+ds1+~cs11.3.9/debian/changelog 2021-11-11 08:00:28.000000000 +0000 @@ -1,3 +1,14 @@ +node-tar (6.0.5+ds1+~cs11.3.9-1+deb11u2) bullseye-security; urgency=medium + + * Team upload + * Fix insufficient symlink protection (Closes: CVE-2021-37701) + * Fix arbitrary file creation/overwrite and arbitrary code execution + vulnerability (Closes: CVE-2021-37712) + * Don't apply umask when uncompressing to avoid creating world writable + directories + + -- Yadd Thu, 11 Nov 2021 09:00:28 +0100 + node-tar (6.0.5+ds1+~cs11.3.9-1+deb11u1) bullseye; urgency=medium * Team upload diff -Nru node-tar-6.0.5+ds1+~cs11.3.9/debian/patches/CVE-2021-37701.patch node-tar-6.0.5+ds1+~cs11.3.9/debian/patches/CVE-2021-37701.patch --- node-tar-6.0.5+ds1+~cs11.3.9/debian/patches/CVE-2021-37701.patch 1970-01-01 00:00:00.000000000 +0000 +++ node-tar-6.0.5+ds1+~cs11.3.9/debian/patches/CVE-2021-37701.patch 2021-11-11 08:00:28.000000000 +0000 @@ -0,0 +1,419 @@ +Description: normalize paths on Windows systems +Author: isaacs +Origin: upstream, https://github.com/npm/node-tar/commit/53602669 +Bug: https://github.com/npm/node-tar/security/advisories/GHSA-9r2w-394v-53qc +Forwarded: not-needed +Reviewed-By: Yadd +Last-Update: 2021-11-11 + +--- a/lib/mkdir.js ++++ b/lib/mkdir.js +@@ -8,6 +8,7 @@ + const fs = require('fs') + const path = require('path') + const chownr = require('chownr') ++const normPath = require('./normalize-windows-path.js') + + class SymlinkError extends Error { + constructor (symlink, path) { +@@ -33,7 +34,11 @@ + } + } + ++const cGet = (cache, key) => cache.get(normPath(key)) ++const cSet = (cache, key, val) => cache.set(normPath(key), val) ++ + const mkdir = module.exports = (dir, opt, cb) => { ++ dir = normPath(dir) + // if there's any overlap between mask and mode, + // then we'll need an explicit chmod + const umask = opt.umask +@@ -49,13 +54,13 @@ + const preserve = opt.preserve + const unlink = opt.unlink + const cache = opt.cache +- const cwd = opt.cwd ++ const cwd = normPath(opt.cwd) + + const done = (er, created) => { + if (er) + cb(er) + else { +- cache.set(dir, true) ++ cSet(cache, dir, true) + if (created && doChown) + chownr(created, uid, gid, er => done(er)) + else if (needChmod) +@@ -65,7 +70,7 @@ + } + } + +- if (cache && cache.get(dir) === true) ++ if (cache && cGet(cache, dir) === true) + return done() + + if (dir === cwd) +@@ -79,7 +84,7 @@ + return mkdirp(dir, {mode}).then(made => done(null, made), done) + + const sub = path.relative(cwd, dir) +- const parts = sub.split(/\/|\\/) ++ const parts = sub.split('/') + mkdir_(cwd, parts, mode, cache, unlink, cwd, null, done) + } + +@@ -88,7 +93,7 @@ + return cb(null, created) + const p = parts.shift() + const part = base + '/' + p +- if (cache.get(part)) ++ if (cGet(cache, part)) + return mkdir_(part, parts, mode, cache, unlink, cwd, created, cb) + fs.mkdir(part, mode, onmkdir(part, parts, mode, cache, unlink, cwd, created, cb)) + } +@@ -122,6 +127,7 @@ + } + + const mkdirSync = module.exports.sync = (dir, opt) => { ++ dir = normPath(dir) + // if there's any overlap between mask and mode, + // then we'll need an explicit chmod + const umask = opt.umask +@@ -137,17 +143,17 @@ + const preserve = opt.preserve + const unlink = opt.unlink + const cache = opt.cache +- const cwd = opt.cwd ++ const cwd = normPath(opt.cwd) + + const done = (created) => { +- cache.set(dir, true) ++ cSet(cache, dir, true) + if (created && doChown) + chownr.sync(created, uid, gid) + if (needChmod) + fs.chmodSync(dir, mode) + } + +- if (cache && cache.get(dir) === true) ++ if (cache && cGet(cache, dir) === true) + return done() + + if (dir === cwd) { +@@ -169,19 +175,19 @@ + return done(mkdirp.sync(dir, mode)) + + const sub = path.relative(cwd, dir) +- const parts = sub.split(/\/|\\/) ++ const parts = sub.split('/') + let created = null + for (let p = parts.shift(), part = cwd; + p && (part += '/' + p); + p = parts.shift()) { + +- if (cache.get(part)) ++ if (cGet(cache, part)) + continue + + try { + fs.mkdirSync(part, mode) + created = created || part +- cache.set(part, true) ++ cSet(cache, part, true) + } catch (er) { + if (er.path && path.dirname(er.path) === cwd && + (er.code === 'ENOTDIR' || er.code === 'ENOENT')) +@@ -189,13 +195,13 @@ + + const st = fs.lstatSync(part) + if (st.isDirectory()) { +- cache.set(part, true) ++ cSet(cache, part, true) + continue + } else if (unlink) { + fs.unlinkSync(part) + fs.mkdirSync(part, mode) + created = created || part +- cache.set(part, true) ++ cSet(cache, part, true) + continue + } else if (st.isSymbolicLink()) + return new SymlinkError(part, part + '/' + parts.join('/')) +--- /dev/null ++++ b/lib/normalize-windows-path.js +@@ -0,0 +1,8 @@ ++// on windows, either \ or / are valid directory separators. ++// on unix, \ is a valid character in filenames. ++// so, on windows, and only on windows, we replace all \ chars with /, ++// so that we can use / as our one and only directory separator char. ++ ++const platform = process.env.TESTING_TAR_FAKE_PLATFORM || process.platform ++module.exports = platform !== 'win32' ? p => p ++ : p => p.replace(/\\/g, '/') +--- a/lib/pack.js ++++ b/lib/pack.js +@@ -54,6 +54,7 @@ + const fs = require('fs') + const path = require('path') + const warner = require('./warn-mixin.js') ++const normPath = require('./normalize-windows-path.js') + + const Pack = warner(class Pack extends MiniPass { + constructor (opt) { +@@ -66,7 +67,7 @@ + this.preservePaths = !!opt.preservePaths + this.strict = !!opt.strict + this.noPax = !!opt.noPax +- this.prefix = (opt.prefix || '').replace(/(\\|\/)+$/, '') ++ this.prefix = normPath(opt.prefix || '') + this.linkCache = opt.linkCache || new Map() + this.statCache = opt.statCache || new Map() + this.readdirCache = opt.readdirCache || new Map() +@@ -133,7 +134,7 @@ + } + + [ADDTARENTRY] (p) { +- const absolute = path.resolve(this.cwd, p.path) ++ const absolute = normPath(path.resolve(this.cwd, p.path)) + if (this.prefix) + p.path = this.prefix + '/' + p.path.replace(/^\.(\/+|$)/, '') + +@@ -152,7 +153,7 @@ + } + + [ADDFSENTRY] (p) { +- const absolute = path.resolve(this.cwd, p) ++ const absolute = normPath(path.resolve(this.cwd, p)) + if (this.prefix) + p = this.prefix + '/' + p.replace(/^\.(\/+|$)/, '') + +--- a/lib/path-reservations.js ++++ b/lib/path-reservations.js +@@ -7,6 +7,7 @@ + // while still allowing maximal safe parallelization. + + const assert = require('assert') ++const normPath = require('./normalize-windows-path.js') + + module.exports = () => { + // path => [function or Set] +@@ -20,8 +21,9 @@ + // return a set of parent dirs for a given path + const { join } = require('path') + const getDirs = path => +- join(path).split(/[\\\/]/).slice(0, -1).reduce((set, path) => +- set.length ? set.concat(join(set[set.length-1], path)) : [path], []) ++ normPath(join(path)).split('/').slice(0, -1).reduce((set, path) => ++ set.length ? set.concat(normPath(join(set[set.length - 1], path))) ++ : [path], []) + + // functions currently running + const running = new Set() +--- /dev/null ++++ b/lib/strip-trailing-slashes.js +@@ -0,0 +1,13 @@ ++// warning: extremely hot code path. ++// This has been meticulously optimized for use ++// within npm install on large package trees. ++// Do not edit without careful benchmarking. ++module.exports = str => { ++ let i = str.length - 1 ++ let slashesStart = -1 ++ while (i > -1 && str.charAt(i) === '/') { ++ slashesStart = i ++ i-- ++ } ++ return slashesStart === -1 ? str : str.slice(0, slashesStart) ++} +--- a/lib/unpack.js ++++ b/lib/unpack.js +@@ -17,6 +17,7 @@ + const wc = require('./winchars.js') + const pathReservations = require('./path-reservations.js') + const stripAbsolutePath = require('./strip-absolute-path.js') ++const normPath = require('./normalize-windows-path.js') + + const ONENTRY = Symbol('onEntry') + const CHECKFS = Symbol('checkFs') +@@ -94,6 +95,17 @@ + : b === b >>> 0 ? b + : c + ++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() ++ for (const path of cache.keys()) { ++ const plower = path.toLowerCase() ++ if (plower === abs || plower.toLowerCase().indexOf(abs + '/') === 0) ++ cache.delete(path) ++ } ++} ++ + class Unpack extends Parser { + constructor (opt) { + if (!opt) +@@ -170,7 +182,7 @@ + // links, and removes symlink directories rather than erroring + this.unlink = !!opt.unlink + +- this.cwd = path.resolve(opt.cwd || process.cwd()) ++ this.cwd = normPath(path.resolve(opt.cwd || process.cwd())) + this.strip = +opt.strip || 0 + this.processUmask = process.umask() + this.umask = typeof opt.umask === 'number' ? opt.umask : this.processUmask +@@ -200,21 +212,21 @@ + + [CHECKPATH] (entry) { + if (this.strip) { +- const parts = entry.path.split(/\/|\\/) ++ const parts = normPath(entry.path).split('/') + if (parts.length < this.strip) + return false + entry.path = parts.slice(this.strip).join('/') + + if (entry.type === 'Link') { +- const linkparts = entry.linkpath.split(/\/|\\/) ++ const linkparts = normPath(entry.linkpath).split('/') + if (linkparts.length >= this.strip) + entry.linkpath = linkparts.slice(this.strip).join('/') + } + } + + if (!this.preservePaths) { +- const p = entry.path +- if (p.match(/(^|\/|\\)\.\.(\\|\/|$)/)) { ++ const p = normPath(entry.path) ++ if (p.split('/').includes('..')) { + this.warn('TAR_ENTRY_ERROR', `path contains '..'`, { + entry, + path: p, +@@ -242,9 +254,9 @@ + } + + if (path.isAbsolute(entry.path)) +- entry.absolute = entry.path ++ entry.absolute = normPath(entry.path) + else +- entry.absolute = path.resolve(this.cwd, entry.path) ++ entry.absolute = normPath(path.resolve(this.cwd, entry.path)) + + return true + } +@@ -289,7 +301,7 @@ + } + + [MKDIR] (dir, mode, cb) { +- mkdir(dir, { ++ mkdir(normPath(dir), { + uid: this.uid, + gid: this.gid, + processUid: this.processUid, +@@ -424,7 +436,8 @@ + } + + [HARDLINK] (entry, done) { +- this[LINK](entry, path.resolve(this.cwd, entry.linkpath), 'link', done) ++ const linkpath = normPath(path.resolve(this.cwd, entry.linkpath)) ++ this[LINK](entry, linkpath, 'link', done) + } + + [PEND] () { +@@ -465,14 +478,8 @@ + // then that means we are about to delete the directory we created + // previously, and it is no longer going to be a directory, and neither + // is any of its children. +- if (entry.type !== 'Directory') { +- for (const path of this.dirCache.keys()) { +- if (path === entry.absolute || +- path.indexOf(entry.absolute + '/') === 0 || +- path.indexOf(entry.absolute + '\\') === 0) +- this.dirCache.delete(path) +- } +- } ++ if (entry.type !== 'Directory') ++ pruneCache(this.dirCache, entry.absolute) + + this[MKDIR](path.dirname(entry.absolute), this.dmode, er => { + if (er) { +@@ -524,7 +531,7 @@ + } + + [LINK] (entry, linkpath, link, done) { +- // XXX: get the type ('file' or 'dir') for windows ++ // XXX: get the type ('symlink' or 'junction') for windows + fs[link](linkpath, entry.absolute, er => { + if (er) + return this[ONERROR](er, entry) +@@ -541,14 +548,8 @@ + } + + [CHECKFS] (entry) { +- if (entry.type !== 'Directory') { +- for (const path of this.dirCache.keys()) { +- if (path === entry.absolute || +- path.indexOf(entry.absolute + '/') === 0 || +- path.indexOf(entry.absolute + '\\') === 0) +- this.dirCache.delete(path) +- } +- } ++ if (entry.type !== 'Directory') ++ pruneCache(this.dirCache, entry.absolute) + + const er = this[MKDIR](path.dirname(entry.absolute), this.dmode, neverCalled) + if (er) +@@ -671,7 +672,7 @@ + + [MKDIR] (dir, mode) { + try { +- return mkdir.sync(dir, { ++ return mkdir.sync(normPath(dir), { + uid: this.uid, + gid: this.gid, + processUid: this.processUid, +--- a/lib/write-entry.js ++++ b/lib/write-entry.js +@@ -5,6 +5,8 @@ + const ReadEntry = require('./read-entry.js') + const fs = require('fs') + const path = require('path') ++const normPath = require('./normalize-windows-path.js') ++const stripSlash = require('./strip-trailing-slashes.js') + + const types = require('./types.js') + const maxReadSize = 16 * 1024 * 1024 +@@ -35,7 +37,7 @@ + super(opt) + if (typeof p !== 'string') + throw new TypeError('path is required') +- this.path = p ++ this.path = normPath(p) + // suppress atime, ctime, uid, gid, uname, gname + this.portable = !!opt.portable + // until node has builtin pwnam functions, this'll have to do +@@ -69,7 +71,7 @@ + p = p.replace(/\\/g, '/') + } + +- this.absolute = opt.absolute || path.resolve(this.cwd, p) ++ this.absolute = normPath(opt.absolute || path.resolve(this.cwd, p)) + + if (this.path === '') + this.path = './' +@@ -175,14 +177,14 @@ + } + + [ONREADLINK] (linkpath) { +- this.linkpath = linkpath.replace(/\\/g, '/') ++ this.linkpath = normPath(linkpath) + this[HEADER]() + this.end() + } + + [HARDLINK] (linkpath) { + this.type = 'Link' +- this.linkpath = path.relative(this.cwd, linkpath).replace(/\\/g, '/') ++ this.linkpath = normPath(path.relative(this.cwd, linkpath)) + this.stat.size = 0 + this[HEADER]() + this.end() diff -Nru node-tar-6.0.5+ds1+~cs11.3.9/debian/patches/CVE-2021-37712.patch node-tar-6.0.5+ds1+~cs11.3.9/debian/patches/CVE-2021-37712.patch --- node-tar-6.0.5+ds1+~cs11.3.9/debian/patches/CVE-2021-37712.patch 1970-01-01 00:00:00.000000000 +0000 +++ node-tar-6.0.5+ds1+~cs11.3.9/debian/patches/CVE-2021-37712.patch 2021-11-11 08:00:28.000000000 +0000 @@ -0,0 +1,90 @@ +Description: prevent path escape using drive-relative paths +Author: isaacs +Origin: upstream, https://github.com/npm/node-tar/commit/875a37e3 +Bug: https://github.com/npm/node-tar/security/advisories/GHSA-qq89-hq3f-393p +Forwarded: not-needed +Reviewed-By: Yadd +Last-Update: 2021-11-11 + +--- a/lib/strip-absolute-path.js ++++ b/lib/strip-absolute-path.js +@@ -2,13 +2,23 @@ + const { isAbsolute, parse } = require('path').win32 + + // 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] + } +--- a/lib/unpack.js ++++ b/lib/unpack.js +@@ -45,6 +45,8 @@ + const GID = Symbol('gid') + const crypto = require('crypto') + const getFlag = require('./get-write-flag.js') ++const platform = process.env.TESTING_TAR_FAKE_PLATFORM || process.platform ++const isWindows = platform === 'win32' + + /* istanbul ignore next */ + const neverCalled = () => { +@@ -226,7 +228,8 @@ + + if (!this.preservePaths) { + 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 '..'`, { + entry, + path: p, +@@ -234,8 +237,7 @@ + return false + } + +- // 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) + if (root) { + entry.path = stripped +@@ -258,6 +260,22 @@ + else + entry.absolute = normPath(path.resolve(this.cwd, entry.path)) + ++ // 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 ++ } ++ + return true + } + diff -Nru node-tar-6.0.5+ds1+~cs11.3.9/debian/patches/add-noChmod-option.patch node-tar-6.0.5+ds1+~cs11.3.9/debian/patches/add-noChmod-option.patch --- node-tar-6.0.5+ds1+~cs11.3.9/debian/patches/add-noChmod-option.patch 1970-01-01 00:00:00.000000000 +0000 +++ node-tar-6.0.5+ds1+~cs11.3.9/debian/patches/add-noChmod-option.patch 2021-11-11 08:00:28.000000000 +0000 @@ -0,0 +1,109 @@ +Description: add noChmod option + Else using `npm install foo` create a world writable node_modules/foo + directory. + This allows a way to suppress the call to process.umask() while + still being as compliant as possible with the modes as defined + in the tarball entries. +Author: isaacs +Origin: upstream, https://github.com/npm/node-tar/pull/270 +Forwarded: not-needed +Reviewed-Bt: Yadd +Last-Update: 2021-11-11 + +--- a/lib/unpack.js ++++ b/lib/unpack.js +@@ -186,11 +186,14 @@ + + this.cwd = normPath(path.resolve(opt.cwd || process.cwd())) + this.strip = +opt.strip || 0 +- this.processUmask = process.umask() ++ // if we're not chmodding, then we don't need the process umask ++ this.processUmask = opt.noChmod ? 0 : process.umask() + this.umask = typeof opt.umask === 'number' ? opt.umask : this.processUmask ++ + // default mode for dirs created as parents + this.dmode = opt.dmode || (0o0777 & (~this.umask)) + this.fmode = opt.fmode || (0o0666 & (~this.umask)) ++ + this.on('entry', entry => this[ONENTRY](entry)) + } + +@@ -329,7 +332,8 @@ + unlink: this.unlink, + cache: this.dirCache, + cwd: this.cwd, +- mode: mode ++ mode: mode, ++ noChmod: this.noChmod, + }, cb) + } + +@@ -513,7 +517,7 @@ + } + else if (st.isDirectory()) { + if (entry.type === 'Directory') { +- if (!entry.mode || (st.mode & 0o7777) === entry.mode) ++ if (!this.noChmod && (!entry.mode || (st.mode & 0o7777) === entry.mode)) + this[MAKEFS](null, entry, done) + else + fs.chmod(entry.absolute, entry.mode, +@@ -582,7 +586,7 @@ + try { + if (st.isDirectory()) { + if (entry.type === 'Directory') { +- if (entry.mode && (st.mode & 0o7777) !== entry.mode) ++ if (!this.noChmod && entry.mode && (st.mode & 0o7777) !== entry.mode) + fs.chmodSync(entry.absolute, entry.mode) + } else + fs.rmdirSync(entry.absolute) +--- a/test/unpack.js ++++ b/test/unpack.js +@@ -1918,6 +1918,48 @@ + }) + }) + ++t.test('dont use explicit chmod if noChmod flag set', t => { ++ process.umask(0o022) ++ const { umask } = process ++ t.teardown(() => process.umask = umask) ++ process.umask = () => { ++ throw new Error('should not call process.umask()') ++ } ++ ++ const basedir = path.resolve(unpackdir, 'umask-no-chmod') ++ ++ const data = makeTar([ ++ { ++ path: 'x/y/z', ++ mode: 0o775, ++ type: 'Directory', ++ }, ++ '', ++ '', ++ ]) ++ ++ const check = t => { ++ const st = fs.statSync(basedir + '/x/y/z') ++ t.equal(st.mode & 0o777, 0o755) ++ rimraf.sync(basedir) ++ t.end() ++ } ++ ++ t.test('async', t => { ++ mkdirp.sync(basedir) ++ const unpack = new Unpack({ cwd: basedir, noChmod: true }) ++ unpack.on('close', _ => check(t)) ++ unpack.end(data) ++ }) ++ ++ return t.test('sync', t => { ++ mkdirp.sync(basedir) ++ const unpack = new Unpack.Sync({ cwd: basedir, noChmod: true}) ++ unpack.end(data) ++ check(t) ++ }) ++}) ++ + t.test('chown implicit dirs and also the entries', t => { + const basedir = path.resolve(unpackdir, 'chownr') + diff -Nru node-tar-6.0.5+ds1+~cs11.3.9/debian/patches/series node-tar-6.0.5+ds1+~cs11.3.9/debian/patches/series --- node-tar-6.0.5+ds1+~cs11.3.9/debian/patches/series 2021-08-11 19:50:15.000000000 +0000 +++ node-tar-6.0.5+ds1+~cs11.3.9/debian/patches/series 2021-11-11 08:00:28.000000000 +0000 @@ -2,3 +2,6 @@ disable-failing-tests.diff CVE-2021-32803.patch CVE-2021-32804.patch +CVE-2021-37701.patch +CVE-2021-37712.patch +add-noChmod-option.patch diff -Nru node-tar-6.0.5+ds1+~cs11.3.9/debian/tests/control node-tar-6.0.5+ds1+~cs11.3.9/debian/tests/control --- node-tar-6.0.5+ds1+~cs11.3.9/debian/tests/control 1970-01-01 00:00:00.000000000 +0000 +++ node-tar-6.0.5+ds1+~cs11.3.9/debian/tests/control 2021-11-11 08:00:28.000000000 +0000 @@ -0,0 +1,3 @@ +Tests: modes +Depends: @, npm +Restrictions: skippable, needs-internet diff -Nru node-tar-6.0.5+ds1+~cs11.3.9/debian/tests/modes node-tar-6.0.5+ds1+~cs11.3.9/debian/tests/modes --- node-tar-6.0.5+ds1+~cs11.3.9/debian/tests/modes 1970-01-01 00:00:00.000000000 +0000 +++ node-tar-6.0.5+ds1+~cs11.3.9/debian/tests/modes 2021-11-11 08:00:28.000000000 +0000 @@ -0,0 +1,21 @@ +#!/bin/sh + +HOME=`mktemp -d` +export HOME +EXIT=0 +cd $HOME +if npm i abab; then + MODE=`stat -c "%a" node_modules/abab` + if test "$MODE" = "777"; then + echo "node-tar created a world writable dir" + ls -l node_modules + EXIT=1 + fi +else + echo "npm failed, skipping test" + rm -rf $HOME + EXIT=77 +fi +cd /tmp +rm -rf $HOME +exit $EXIT