From 25a34f905a0144cebcd41e56b6942117b267e005 Mon Sep 17 00:00:00 2001 From: isaacs Date: Mon, 9 Dec 2019 15:06:36 -0800 Subject: [PATCH] fix: sanitize and validate bin and man link targets --- index.js | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 5f86755..15d0573 100644 --- a/index.js +++ b/index.js @@ -11,10 +11,13 @@ const read = BB.promisify(fs.read, {multiArgs: true}) const chmod = BB.promisify(fs.chmod) const readFile = BB.promisify(fs.readFile) const writeFileAtomic = BB.promisify(require('write-file-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 @@ -77,6 +80,12 @@ function linkBins (pkg, folder, parent, gtop, opts) { 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]) + } + return linkBin(src, dest, linkOpts).then(() => { // bins should always be executable. // XXX skip chmod on windows? @@ -123,7 +132,8 @@ function linkMans (pkg, folder, parent, gtop, opts) { // 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 }, {}) var manpages = pkg.man.filter(function (man) { @@ -146,6 +156,12 @@ function linkMans (pkg, folder, parent, gtop, opts) { 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) return linkIfExists(manSrc, manDest, getLinkOpts(opts, gtop && folder))