diff --git a/node_modules/@npmcli/package-json/lib/normalize.js b/node_modules/@npmcli/package-json/lib/normalize.js index e3b3798488427..1e4545c2d3a1c 100644 --- a/node_modules/@npmcli/package-json/lib/normalize.js +++ b/node_modules/@npmcli/package-json/lib/normalize.js @@ -46,15 +46,14 @@ function normalizePackageBin (pkg, changes) { changes?.push(`removed invalid "bin[${binKey}]"`) continue } - const base = path.join('/', path.basename(binKey.replace(/\\|:/g, '/'))).slice(1) + const base = path.basename(secureAndUnixifyPath(binKey)) if (!base) { delete pkg.bin[binKey] changes?.push(`removed invalid "bin[${binKey}]"`) continue } - const binTarget = path.join('/', pkg.bin[binKey].replace(/\\/g, '/')) - .replace(/\\/g, '/').slice(1) + const binTarget = secureAndUnixifyPath(pkg.bin[binKey]) if (!binTarget) { delete pkg.bin[binKey] @@ -83,6 +82,27 @@ function normalizePackageBin (pkg, changes) { delete pkg.bin } +function normalizePackageMan (pkg, changes) { + if (pkg.man) { + const mans = [] + for (const man of (Array.isArray(pkg.man) ? pkg.man : [pkg.man])) { + if (typeof man !== 'string') { + changes?.push(`removed invalid "man [${man}]"`) + } else { + mans.push(secureAndUnixifyPath(man)) + } + } + + if (!mans.length) { + changes?.push('empty "man" was removed') + } else { + pkg.man = mans + return pkg + } + } + delete pkg.man +} + function isCorrectlyEncodedName (spec) { return !spec.match(/[/@\s+%:]/) && spec === encodeURIComponent(spec) @@ -103,6 +123,19 @@ function isValidScopedPackageName (spec) { rest[1] === encodeURIComponent(rest[1]) } +function unixifyPath (ref) { + return ref.replace(/\\|:/g, '/') +} + +function securePath (ref) { + const secured = path.join('.', path.join('/', unixifyPath(ref))) + return secured.startsWith('.') ? '' : secured +} + +function secureAndUnixifyPath (ref) { + return unixifyPath(securePath(ref)) +} + // We don't want the `changes` array in here by default because this is a hot // path for parsing packuments during install. So the calling method passes it // in if it wants to track changes. @@ -251,7 +284,7 @@ const normalize = async (pkg, { strict, steps, root, changes, allowLegacyCase }) // strip "node_modules/.bin" from scripts entries // remove invalid scripts entries (non-strings) - if (steps.includes('scripts') || steps.includes('scriptpath')) { + if ((steps.includes('scripts') || steps.includes('scriptpath')) && data.scripts !== undefined) { const spre = /^(\.[/\\])?node_modules[/\\].bin[\\/]/ if (typeof data.scripts === 'object') { for (const name in data.scripts) { @@ -325,13 +358,16 @@ const normalize = async (pkg, { strict, steps, root, changes, allowLegacyCase }) } // expand directories.man - if (steps.includes('mans') && !data.man && data.directories?.man) { - const manDir = data.directories.man - const cwd = path.resolve(pkg.path, manDir) - const files = await lazyLoadGlob()('**/*.[0-9]', { cwd }) - data.man = files.map(man => - path.relative(pkg.path, path.join(cwd, man)).split(path.sep).join('/') - ) + if (steps.includes('mans')) { + if (data.directories?.man && !data.man) { + const manDir = secureAndUnixifyPath(data.directories.man) + const cwd = path.resolve(pkg.path, manDir) + const files = await lazyLoadGlob()('**/*.[0-9]', { cwd }) + data.man = files.map(man => + path.relative(pkg.path, path.join(cwd, man)).split(path.sep).join('/') + ) + } + normalizePackageMan(data, changes) } if (steps.includes('bin') || steps.includes('binDir') || steps.includes('binRefs')) { @@ -340,7 +376,7 @@ const normalize = async (pkg, { strict, steps, root, changes, allowLegacyCase }) // expand "directories.bin" if (steps.includes('binDir') && data.directories?.bin && !data.bin) { - const binsDir = path.resolve(pkg.path, path.join('.', path.join('/', data.directories.bin))) + const binsDir = path.resolve(pkg.path, securePath(data.directories.bin)) const bins = await lazyLoadGlob()('**', { cwd: binsDir }) data.bin = bins.reduce((acc, binFile) => { if (binFile && !binFile.startsWith('.')) { diff --git a/node_modules/@npmcli/package-json/package.json b/node_modules/@npmcli/package-json/package.json index 98236f604ecbd..2e87923c4edd2 100644 --- a/node_modules/@npmcli/package-json/package.json +++ b/node_modules/@npmcli/package-json/package.json @@ -1,6 +1,6 @@ { "name": "@npmcli/package-json", - "version": "5.1.0", + "version": "5.1.1", "description": "Programmatic API to update package.json", "main": "lib/index.js", "files": [ @@ -25,7 +25,7 @@ "license": "ISC", "devDependencies": { "@npmcli/eslint-config": "^4.0.0", - "@npmcli/template-oss": "4.21.4", + "@npmcli/template-oss": "4.22.0", "read-package-json": "^7.0.0", "read-package-json-fast": "^3.0.2", "tap": "^16.0.1" @@ -41,14 +41,14 @@ }, "repository": { "type": "git", - "url": "https://github.com/npm/package-json.git" + "url": "git+https://github.com/npm/package-json.git" }, "engines": { "node": "^16.14.0 || >=18.0.0" }, "templateOSS": { "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", - "version": "4.21.4", + "version": "4.22.0", "publish": "true" }, "tap": { diff --git a/package-lock.json b/package-lock.json index 80ea369663f65..8b013b7928022 100644 --- a/package-lock.json +++ b/package-lock.json @@ -91,7 +91,7 @@ "@npmcli/config": "^8.3.2", "@npmcli/fs": "^3.1.1", "@npmcli/map-workspaces": "^3.0.6", - "@npmcli/package-json": "^5.1.0", + "@npmcli/package-json": "^5.1.1", "@npmcli/promise-spawn": "^7.0.2", "@npmcli/redact": "^2.0.0", "@npmcli/run-script": "^8.1.0", @@ -1716,9 +1716,9 @@ } }, "node_modules/@npmcli/package-json": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@npmcli/package-json/-/package-json-5.1.0.tgz", - "integrity": "sha512-1aL4TuVrLS9sf8quCLerU3H9J4vtCtgu8VauYozrmEyU57i/EdKleCnsQ7vpnABIH6c9mnTxcH5sFkO3BlV8wQ==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/package-json/-/package-json-5.1.1.tgz", + "integrity": "sha512-uTq5j/UqUzbOaOxVy+osfOhpqOiLfUZ0Ut33UbcyyAPJbZcJsf4Mrsyb8r58FoIFlofw0iOFsuCA/oDK14VDJQ==", "inBundle": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index c0bd085d1c7f3..0ac4587f4afb2 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,7 @@ "@npmcli/config": "^8.3.2", "@npmcli/fs": "^3.1.1", "@npmcli/map-workspaces": "^3.0.6", - "@npmcli/package-json": "^5.1.0", + "@npmcli/package-json": "^5.1.1", "@npmcli/promise-spawn": "^7.0.2", "@npmcli/redact": "^2.0.0", "@npmcli/run-script": "^8.1.0",