[Pkg-javascript-devel] Bug#947172: buster-pu: package npm/5.8.0+ds6-4+deb10u1
Xavier Guimard
yadd at debian.org
Sun Dec 22 13:14:27 GMT 2019
Package: release.debian.org
Severity: normal
Tags: buster
User: release.debian.org at 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
-------------- next part --------------
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 <yadd at 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 <yadd at 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 at 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 at 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 <yadd at 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 <yadd at 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 <yadd at 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 at 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
More information about the Pkg-javascript-devel
mailing list