From d21ffb35c84ccf8a950b92f40ecbaab89d9d2c7b Mon Sep 17 00:00:00 2001 From: Ragunandhan Mahadevan Date: Tue, 20 Jan 2026 09:41:41 -0800 Subject: [PATCH 1/5] Fixes 6606, shows a warning when a delimiter is present in the path --- lib/set-path.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/set-path.js b/lib/set-path.js index c59c270..68e1e9d 100644 --- a/lib/set-path.js +++ b/lib/set-path.js @@ -1,3 +1,4 @@ +const { log } = require('proc-log') const { resolve, dirname, delimiter } = require('path') // the path here is relative, even though it does not need to be // in order to make the posix tests pass in windows @@ -14,6 +15,11 @@ const setPATH = (projectPath, binPaths, env) => { const pathArr = [] if (binPaths) { + for (const bin of binPaths) { + if (bin.includes(delimiter)) { + log.warn('exec', 'Project path contains delimiter (":"), npx may not behave as expected.') + } + } pathArr.push(...binPaths) } // unshift the ./node_modules/.bin from every folder From 4d104005b22919fee3bac15fba2a966e71aa6e8a Mon Sep 17 00:00:00 2001 From: Ragunandhan Mahadevan Date: Tue, 20 Jan 2026 10:21:35 -0800 Subject: [PATCH 2/5] added test case --- test/make-spawn-args.js | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/test/make-spawn-args.js b/test/make-spawn-args.js index 110f28f..5a30573 100644 --- a/test/make-spawn-args.js +++ b/test/make-spawn-args.js @@ -141,4 +141,34 @@ t.test('spawn args', async t => { })) t.ok(spawk.done()) }) + + await t.test('binPaths containing delimiter logs warning', async t => { + const { delimiter } = require('path') + const { log } = require('proc-log') + const originalWarn = log.warn + let warningLogged = false + + log.warn = (category, message) => { + if (category === 'exec' && message.includes('delimiter')) { + warningLogged = true + } + } + + spawk.spawn( + /.*/, + false, + e => (e.env.PATH || e.env.Path).includes(`/path/with${delimiter}delimiter`) + ) + + await t.resolves(() => runScript({ + pkg, + binPaths: [`/path/with${delimiter}delimiter`], + path: testdir, + event: 'test', + })) + + t.ok(warningLogged, 'warning should be logged when binPath contains delimiter') + t.ok(spawk.done()) + log.warn = originalWarn + }) }) From 1e28b90b06545e99987fc830a5c7aa18368da5aa Mon Sep 17 00:00:00 2001 From: Ragunandhan Mahadevan Date: Tue, 20 Jan 2026 10:27:24 -0800 Subject: [PATCH 3/5] chore: add test coverage for set-path delimiter warning --- test/make-spawn-args.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/make-spawn-args.js b/test/make-spawn-args.js index 5a30573..44579dd 100644 --- a/test/make-spawn-args.js +++ b/test/make-spawn-args.js @@ -153,13 +153,11 @@ t.test('spawn args', async t => { warningLogged = true } } - spawk.spawn( /.*/, false, e => (e.env.PATH || e.env.Path).includes(`/path/with${delimiter}delimiter`) ) - await t.resolves(() => runScript({ pkg, binPaths: [`/path/with${delimiter}delimiter`], From 90b4e423ec9e4ff66357f21ad378424cee0a2dbc Mon Sep 17 00:00:00 2001 From: Ragunandhan Mahadevan Date: Mon, 26 Jan 2026 07:18:50 -0800 Subject: [PATCH 4/5] chore: added event to the warning message to make it generic and useful --- lib/make-spawn-args.js | 2 +- lib/set-path.js | 5 +++-- test/make-spawn-args.js | 22 +++++++++++++++++++++- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/lib/make-spawn-args.js b/lib/make-spawn-args.js index 1c9f02c..73ffbe4 100644 --- a/lib/make-spawn-args.js +++ b/lib/make-spawn-args.js @@ -37,7 +37,7 @@ const makeSpawnArgs = options => { npm_lifecycle_event: event, npm_lifecycle_script: cmd, npm_config_node_gyp, - }) + }, event) const spawnOpts = { env: spawnEnv, diff --git a/lib/set-path.js b/lib/set-path.js index 68e1e9d..baf86e7 100644 --- a/lib/set-path.js +++ b/lib/set-path.js @@ -7,7 +7,7 @@ const nodeGypPath = resolve(__dirname, '../lib/node-gyp-bin') // Windows typically calls its PATH environ 'Path', but this is not // guaranteed, nor is it guaranteed to be the only one. Merge them // all together in the order they appear in the object. -const setPATH = (projectPath, binPaths, env) => { +const setPATH = (projectPath, binPaths, env, event) => { const PATH = Object.keys(env).filter(p => /^path$/i.test(p) && env[p]) .map(p => env[p].split(delimiter)) .reduce((set, p) => set.concat(p.filter(concatted => !set.includes(concatted))), []) @@ -17,7 +17,8 @@ const setPATH = (projectPath, binPaths, env) => { if (binPaths) { for (const bin of binPaths) { if (bin.includes(delimiter)) { - log.warn('exec', 'Project path contains delimiter (":"), npx may not behave as expected.') + const context = event ? `"${event}" script` : 'script execution' + log.warn('run-script', `Project path contains delimiter (":"), ${context} may not behave as expected.`) } } pathArr.push(...binPaths) diff --git a/test/make-spawn-args.js b/test/make-spawn-args.js index 44579dd..17504af 100644 --- a/test/make-spawn-args.js +++ b/test/make-spawn-args.js @@ -149,7 +149,7 @@ t.test('spawn args', async t => { let warningLogged = false log.warn = (category, message) => { - if (category === 'exec' && message.includes('delimiter')) { + if (category === 'run-script' && message.includes('delimiter') && message.includes('"test" script')) { warningLogged = true } } @@ -169,4 +169,24 @@ t.test('spawn args', async t => { t.ok(spawk.done()) log.warn = originalWarn }) + + await t.test('binPaths containing delimiter logs generic warning without event', async t => { + const { delimiter } = require('path') + const { log } = require('proc-log') + const setPATH = require('../lib/set-path.js') + const originalWarn = log.warn + let warningLogged = false + + log.warn = (category, message) => { + if (category === 'run-script' && message.includes('delimiter') && message.includes('script execution')) { + warningLogged = true + } + } + + // Test setPATH directly with no event (simulates npx/exec scenario) + setPATH(testdir, [`/path/with${delimiter}delimiter`], {}, '') + + t.ok(warningLogged, 'warning should be logged with generic message when no event') + log.warn = originalWarn + }) }) From 98f9a47518cdec3ebb552cd19ab1067b6a965984 Mon Sep 17 00:00:00 2001 From: Ragunandhan Mahadevan Date: Mon, 26 Jan 2026 07:30:54 -0800 Subject: [PATCH 5/5] chore: modified implementation to cover windows execution by adding delimiter --- lib/set-path.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/set-path.js b/lib/set-path.js index baf86e7..2730183 100644 --- a/lib/set-path.js +++ b/lib/set-path.js @@ -18,7 +18,7 @@ const setPATH = (projectPath, binPaths, env, event) => { for (const bin of binPaths) { if (bin.includes(delimiter)) { const context = event ? `"${event}" script` : 'script execution' - log.warn('run-script', `Project path contains delimiter (":"), ${context} may not behave as expected.`) + log.warn('run-script', `Project path contains delimiter ("${delimiter}"), ${context} may not behave as expected.`) } } pathArr.push(...binPaths)