Skip to content

Commit fe19e5d

Browse files
fix(cli): avoid DEP0190 warning by removing shell-based npm execution on Windows
1 parent 1824c62 commit fe19e5d

File tree

2 files changed

+9
-11
lines changed

2 files changed

+9
-11
lines changed

cli/src/cli.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ import { initLogger, showToken, logInfo, logWarning, logError } from './logger.t
1212
const DEFAULT_PORT = 31415
1313
const DEFAULT_FRONTEND_URL = 'https://npmx.dev/'
1414
const DEV_FRONTEND_URL = 'http://127.0.0.1:3000/'
15+
const NPM_COMMAND = process.platform === 'win32' ? 'npm.cmd' : 'npm'
1516

1617
async function runNpmLogin(): Promise<boolean> {
1718
return new Promise(resolve => {
18-
const child = spawn('npm', ['login', `--registry=${NPM_REGISTRY_URL}`], {
19+
const child = spawn(NPM_COMMAND, ['login', `--registry=${NPM_REGISTRY_URL}`], {
1920
stdio: 'inherit',
20-
shell: true,
2121
})
2222

2323
child.on('close', code => {

cli/src/npm-client.ts

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { logCommand, logSuccess, logError, logDebug } from './logger.ts'
1111

1212
const execFileAsync = promisify(execFile)
1313
export const NPM_REGISTRY_URL = 'https://registry.npmjs.org/'
14+
const NPM_COMMAND = process.platform === 'win32' ? 'npm.cmd' : 'npm'
1415

1516
function createNpmEnv(overrides: Record<string, string> = {}): Record<string, string> {
1617
return {
@@ -209,7 +210,7 @@ async function execNpmInteractive(
209210
env.npm_config_browser = 'false'
210211
}
211212

212-
const child = pty.spawn('npm', npmArgs, {
213+
const child = pty.spawn(NPM_COMMAND, npmArgs, {
213214
name: 'xterm-256color',
214215
cols: 120,
215216
rows: 30,
@@ -331,14 +332,12 @@ async function execNpm(args: string[], options: ExecNpmOptions = {}): Promise<Np
331332
}
332333

333334
try {
334-
logDebug('Executing npm command:', { command: 'npm', args: npmArgs })
335-
// Use execFile instead of exec to avoid shell injection vulnerabilities
336-
// On Windows, shell: true is required to execute .cmd files (like npm.cmd)
337-
// On Unix, we keep it false for better security and performance
338-
const { stdout, stderr } = await execFileAsync('npm', npmArgs, {
335+
logDebug('Executing npm command:', { command: NPM_COMMAND, args: npmArgs })
336+
// Use execFile instead of exec to avoid shell injection vulnerabilities.
337+
// Use npm.cmd on Windows to avoid shell wrapping and DEP0190 warnings.
338+
const { stdout, stderr } = await execFileAsync(NPM_COMMAND, npmArgs, {
339339
timeout: 60000,
340340
env: createNpmEnv(),
341-
shell: process.platform === 'win32',
342341
})
343342

344343
logDebug('Command succeeded:', { stdout, stderr })
@@ -610,11 +609,10 @@ export async function packageInit(
610609
logCommand(`${displayCmd} (in temp dir for ${name})`)
611610

612611
try {
613-
const { stdout, stderr } = await execFileAsync('npm', npmArgs, {
612+
const { stdout, stderr } = await execFileAsync(NPM_COMMAND, npmArgs, {
614613
timeout: 60000,
615614
cwd: tempDir,
616615
env: createNpmEnv(),
617-
shell: process.platform === 'win32',
618616
})
619617

620618
logSuccess(`Published ${name}@0.0.0`)

0 commit comments

Comments
 (0)