Package: release.debian.org
Severity: normal
Tags: buster
User: release.debian....@packages.debian.org
Usertags: pu

Hi,

npm is vulnerable to some CVEs (CVE-2019-16775, CVE-2019-16776,
CVE-2019-16777). This patch groups patches from differents sub modules
affected and add a new module (npm-normalize-package-bin package) used
by these fixes.

After discussion with security team, these CVEs will be tagged as
no-dsa.

Cheers,
Xavier
diff --git a/debian/changelog b/debian/changelog
index 85e9028..d7b986f 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,10 @@
+npm (5.8.0+ds6-4+deb10u1) buster; urgency=medium
+
+  * Add patches to fix arbitrary path access
+    (Closes: CVE-2019-16775, CVE-2019-16776, CVE-2019-16777)
+
+ -- Xavier Guimard <y...@debian.org>  Sun, 15 Dec 2019 16:19:02 +0100
+
 npm (5.8.0+ds6-4) unstable; urgency=medium
 
   * Team upload
diff --git a/debian/patches/CVE-2019-16775-add-npm-normalize-package-bin.diff 
b/debian/patches/CVE-2019-16775-add-npm-normalize-package-bin.diff
new file mode 100644
index 0000000..a3c7b45
--- /dev/null
+++ b/debian/patches/CVE-2019-16775-add-npm-normalize-package-bin.diff
@@ -0,0 +1,167 @@
+Description: Add npm-normalize-package-bin package
+ Needed to CVE-2019-16775 fix
+Author: isaacs
+Bug: https://github.com/npm/cli/security/advisories/GHSA-x8qc-rrcw-4r46
+Forwarded: not-needed
+Reviewed-By: Xavier Guimard <y...@debian.org>
+Last-Update: 2019-12-15
+
+--- /dev/null
++++ b/node_modules/npm-normalize-package-bin/LICENSE
+@@ -0,0 +1,15 @@
++The ISC License
++
++Copyright (c) npm, Inc.
++
++Permission to use, copy, modify, and/or distribute this software for any
++purpose with or without fee is hereby granted, provided that the above
++copyright notice and this permission notice appear in all copies.
++
++THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
++WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
++MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
++ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
++ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
++IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+--- /dev/null
++++ b/node_modules/npm-normalize-package-bin/README.md
+@@ -0,0 +1,14 @@
++# npm-normalize-package-bin
++
++Turn any flavor of allowable package.json bin into a normalized object.
++
++## API
++
++```js
++const normalize = require('npm-normalize-package-bin')
++const pkg = {name: 'foo', bin: 'bar'}
++console.log(normalize(pkg)) // {name:'foo', bin:{foo: 'bar'}}
++```
++
++Also strips out weird dots and slashes to prevent accidental and/or
++malicious bad behavior when the package is installed.
+--- /dev/null
++++ b/node_modules/npm-normalize-package-bin/index.js
+@@ -0,0 +1,60 @@
++// pass in a manifest with a 'bin' field here, and it'll turn it
++// into a properly santized bin object
++const {join, basename} = require('path')
++
++const normalize = pkg =>
++  !pkg.bin ? removeBin(pkg)
++  : typeof pkg.bin === 'string' ? normalizeString(pkg)
++  : Array.isArray(pkg.bin) ? normalizeArray(pkg)
++  : typeof pkg.bin === 'object' ? normalizeObject(pkg)
++  : removeBin(pkg)
++
++const normalizeString = pkg => {
++  if (!pkg.name)
++    return removeBin(pkg)
++  pkg.bin = { [pkg.name]: pkg.bin }
++  return normalizeObject(pkg)
++}
++
++const normalizeArray = pkg => {
++  pkg.bin = pkg.bin.reduce((acc, k) => {
++    acc[basename(k)] = k
++    return acc
++  }, {})
++  return normalizeObject(pkg)
++}
++
++const removeBin = pkg => {
++  delete pkg.bin
++  return pkg
++}
++
++const normalizeObject = pkg => {
++  const orig = pkg.bin
++  const clean = {}
++  let hasBins = false
++  Object.keys(orig).forEach(binKey => {
++    const base = join('/', basename(binKey.replace(/\\|:/g, '/'))).substr(1)
++
++    if (typeof orig[binKey] !== 'string' || !base)
++      return
++
++    const binTarget = join('/', orig[binKey])
++      .replace(/\\/g, '/').substr(1)
++
++    if (!binTarget)
++      return
++
++    clean[base] = binTarget
++    hasBins = true
++  })
++
++  if (hasBins)
++    pkg.bin = clean
++  else
++    delete pkg.bin
++
++  return pkg
++}
++
++module.exports = normalize
+--- /dev/null
++++ b/node_modules/npm-normalize-package-bin/package.json
+@@ -0,0 +1,58 @@
++{
++  "_from": "npm-normalize-package-bin",
++  "_id": "npm-normalize-package-bin@1.0.1",
++  "_inBundle": false,
++  "_integrity": 
"sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==",
++  "_location": "/npm-normalize-package-bin",
++  "_phantomChildren": {},
++  "_requested": {
++    "type": "tag",
++    "registry": true,
++    "raw": "npm-normalize-package-bin",
++    "name": "npm-normalize-package-bin",
++    "escapedName": "npm-normalize-package-bin",
++    "rawSpec": "",
++    "saveSpec": null,
++    "fetchSpec": "latest"
++  },
++  "_requiredBy": [
++    "#USER",
++    "/"
++  ],
++  "_resolved": 
"https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz";,
++  "_shasum": "6e79a41f23fd235c0623218228da7d9c23b8f6e2",
++  "_spec": "npm-normalize-package-bin",
++  "_where": "/tmp/tt",
++  "author": {
++    "name": "Isaac Z. Schlueter",
++    "email": "i...@izs.me",
++    "url": "https://izs.me";
++  },
++  "bugs": {
++    "url": "https://github.com/npm/npm-normalize-package-bin/issues";
++  },
++  "bundleDependencies": false,
++  "deprecated": false,
++  "description": "Turn any flavor of allowable package.json bin into a 
normalized object",
++  "devDependencies": {
++    "tap": "^14.10.2"
++  },
++  "homepage": "https://github.com/npm/npm-normalize-package-bin#readme";,
++  "license": "ISC",
++  "name": "npm-normalize-package-bin",
++  "repository": {
++    "type": "git",
++    "url": "git+https://github.com/npm/npm-normalize-package-bin.git";
++  },
++  "scripts": {
++    "postpublish": "git push origin --follow-tags",
++    "postversion": "npm publish",
++    "preversion": "npm test",
++    "snap": "tap",
++    "test": "tap"
++  },
++  "tap": {
++    "check-coverage": true
++  },
++  "version": "1.0.1"
++}
diff --git a/debian/patches/CVE-2019-16775-bin-links.diff 
b/debian/patches/CVE-2019-16775-bin-links.diff
new file mode 100644
index 0000000..5a2f946
--- /dev/null
+++ b/debian/patches/CVE-2019-16775-bin-links.diff
@@ -0,0 +1,60 @@
+Description: sanitize and validate bin and man link targets
+ Part of CVE-2019-16776 fix
+Author: isaacs
+Origin: upstream, https://github.com/npm/bin-links/commit/25a34f9
+Bug: https://github.com/npm/cli/security/advisories/GHSA-x8qc-rrcw-4r46
+Forwarded: not-needed
+Reviewed-By: Xavier Guimard <y...@debian.org>
+Last-Update: 2019-12-15
+
+--- a/node_modules/bin-links/index.js
++++ b/node_modules/bin-links/index.js
+@@ -12,10 +12,12 @@
+ const chmod = BB.promisify(fs.chmod)
+ const Transform = require('stream').Transform
+ const fsWriteStreamAtomic = require('fs-write-stream-atomic')
++const normalize = require('npm-normalize-package-bin')
+ 
+ module.exports = BB.promisify(binLinks)
+ 
+ function binLinks (pkg, folder, global, opts, cb) {
++  pkg = normalize(pkg)
+   // if it's global, and folder is in {prefix}/node_modules,
+   // then bins are in {prefix}/bin
+   // otherwise, then bins are in folder/../.bin
+@@ -107,6 +109,12 @@
+     var dest = path.resolve(binRoot, bin)
+     var src = path.resolve(folder, pkg.bin[bin])
+ 
++    /* istanbul ignore if - that unpossible */
++    if (src.indexOf(folder) !== 0) {
++      throw new Error('invalid bin entry for package ' +
++        pkg._id + '. key=' + bin + ', value=' + pkg.bin[bin])
++    }
++
+     linkBin(src, dest, linkOpts, function (er) {
+       if (er) return cb(er)
+       // bins should always be executable.
+@@ -157,7 +165,8 @@
+   // make sure that the mans are unique.
+   // otherwise, if there are dupes, it'll fail with EEXIST
+   var set = pkg.man.reduce(function (acc, man) {
+-    acc[path.basename(man)] = man
++    const cleanMan = path.join('/', man).replace(/\\|:/g, '/').substr(1)
++    acc[path.basename(man)] = cleanMan
+     return acc
+   }, {})
+   pkg.man = pkg.man.filter(function (man) {
+@@ -180,6 +189,12 @@
+     var sxn = parseMan[2]
+     var bn = path.basename(stem)
+     var manSrc = path.resolve(folder, man)
++    /* istanbul ignore if - that unpossible */
++    if (manSrc.indexOf(folder) !== 0) {
++      throw new Error('invalid man entry for package ' +
++        pkg._id + '. man=' + manSrc)
++    }
++
+     var manDest = path.join(manRoot, 'man' + sxn, bn)
+ 
+     linkIfExists(manSrc, manDest, getLinkOpts(opts, gtop && folder), cb)
diff --git a/debian/patches/CVE-2019-16775-npm-packlist.diff 
b/debian/patches/CVE-2019-16775-npm-packlist.diff
new file mode 100644
index 0000000..f1b7a08
--- /dev/null
+++ b/debian/patches/CVE-2019-16775-npm-packlist.diff
@@ -0,0 +1,29 @@
+Description: sanitize and normalize package bin field
+ Part of CVE-2019-16776 fix
+Author: isaacs
+Origin: upstream, https://github.com/npm/npm-packlist/commit/ec4d56e
+Bug: https://github.com/npm/cli/security/advisories/GHSA-x8qc-rrcw-4r46
+Forwarded: not-needed
+Reviewed-By: Xavier Guimard <y...@debian.org>
+Last-Update: 2019-12-15
+
+--- a/node_modules/npm-packlist/index.js
++++ b/node_modules/npm-packlist/index.js
+@@ -17,6 +17,8 @@
+ const packageNecessaryRules = Symbol('package-necessary-rules')
+ const path = require('path')
+ 
++const normalizePackageBin = require('npm-normalize-package-bin')
++
+ const defaultRules = [
+   '.npmignore',
+   '.gitignore',
+@@ -154,7 +156,7 @@
+   onReadIgnoreFile (file, data, then) {
+     if (file === 'package.json')
+       try {
+-        this.onPackageJson(file, JSON.parse(data), then)
++        this.onPackageJson(file, normalizePackageBin(JSON.parse(data)), then)
+       } catch (er) {
+         // ignore package.json files that are not json
+         then()
diff --git a/debian/patches/CVE-2019-16775-pacote.diff 
b/debian/patches/CVE-2019-16775-pacote.diff
new file mode 100644
index 0000000..bb52001
--- /dev/null
+++ b/debian/patches/CVE-2019-16775-pacote.diff
@@ -0,0 +1,58 @@
+Description: sanitize and normalize package bin field
+ Part of CVE-2019-16776 fix
+Author: isaacs
+Origin: upstream, https://github.com/npm/pacote/commit/6f229f7
+Bug: https://github.com/npm/cli/security/advisories/GHSA-x8qc-rrcw-4r46
+Forwarded: not-needed
+Reviewed-By: Xavier Guimard <y...@debian.org>
+Last-Update: 2019-12-15
+
+--- a/node_modules/pacote/lib/fetchers/directory.js
++++ b/node_modules/pacote/lib/fetchers/directory.js
+@@ -8,6 +8,7 @@
+ const path = require('path')
+ const pipe = BB.promisify(require('mississippi').pipe)
+ const through = require('mississippi').through
++const normalizePackageBin = require('npm-normalize-package-bin')
+ 
+ const readFileAsync = BB.promisify(require('fs').readFile)
+ 
+@@ -46,7 +47,7 @@
+       } else {
+         return pkg
+       }
+-    })
++    }).then(pkg => normalizePackageBin(pkg))
+   },
+ 
+   // As of npm@5, the npm installer doesn't pack + install directories: it 
just
+--- a/node_modules/pacote/lib/finalize-manifest.js
++++ b/node_modules/pacote/lib/finalize-manifest.js
+@@ -13,6 +13,7 @@
+ const pipe = BB.promisify(require('mississippi').pipe)
+ const ssri = require('ssri')
+ const tar = require('tar')
++const normalizePackageBin = require('npm-normalize-package-bin')
+ 
+ // `finalizeManifest` takes as input the various kinds of manifests that
+ // manifest handlers ('lib/fetchers/*.js#manifest()') return, and makes sure
+@@ -102,17 +103,8 @@
+   this._shrinkwrap = pkg._shrinkwrap || fromTarball._shrinkwrap || null
+   this.bin = pkg.bin || fromTarball.bin || null
+ 
+-  if (this.bin && Array.isArray(this.bin)) {
+-    // Code yanked from read-package-json.
+-    const m = (pkg.directories && pkg.directories.bin) || '.'
+-    this.bin = this.bin.reduce((acc, mf) => {
+-      if (mf && mf.charAt(0) !== '.') {
+-        const f = path.basename(mf)
+-        acc[f] = path.join(m, mf)
+-      }
+-      return acc
+-    }, {})
+-  }
++  // turn arrays and strings into a legit object, strip out bad stuff
++  normalizePackageBin(this)
+ 
+   this._id = null
+ 
diff --git a/debian/patches/series b/debian/patches/series
index c29dbfe..95031c5 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -9,3 +9,7 @@
 2014_remove_readable_stream.patch
 2015_use_system_libnpx_1.patch
 new-lru-cache.patch
+CVE-2019-16775-bin-links.diff
+CVE-2019-16775-npm-packlist.diff
+CVE-2019-16775-pacote.diff
+CVE-2019-16775-add-npm-normalize-package-bin.diff
-- 
Pkg-javascript-devel mailing list
Pkg-javascript-devel@alioth-lists.debian.net
https://alioth-lists.debian.net/cgi-bin/mailman/listinfo/pkg-javascript-devel

Reply via email to