Skip to content

Commit 0da5368

Browse files
felixtrzmeta-codesync[bot]
authored andcommitted
fix(cli): spawn package managers with shell on Windows
Summary: `iwsdk dev up` (and therefore `npm run dev`) failed on Windows with the generic error "Failed to start the dev process". `handleDevUp` (`packages/cli/src/commands/dev.ts`) spawns the detected package manager (`npm`/`pnpm`/`yarn`) without `shell: true`. On Windows those binaries are `.cmd` shims, which Node's `child_process.spawn` cannot launch without a shell — the spawn fails with `ENOENT`, `child.pid` is `undefined`, and the CLI throws at the `typeof child.pid !== 'number'` guard. macOS/Linux are unaffected because the package managers are real executables on `PATH`. `shell: true` is the only reliable fix. The "append `.cmd`" alternative (`spawn('npm.cmd', …)` without a shell) is not viable: on Node >=18.20.2 / 20.12.2 / 21.7.3 (CVE-2024-27980 mitigation) it throws `EINVAL` synchronously. This change adds `shell: process.platform === 'win32'` to the spawn in `handleDevUp`; the guard makes it a no-op on macOS/Linux, so behavior there is byte-for-byte unchanged. `packages/cli/src/hzdb-telemetry.ts` carried the same latent bug for `npx`: its spawn error is swallowed, so hzdb telemetry silently never fired on Windows. The same `shell: process.platform === 'win32'` guard is applied there. Teardown is unaffected: with `shell: true`, `child.pid` becomes the `cmd.exe` wrapper PID, but `terminateRuntimeWorkspace` also kills `state.session.pid` — the real Vite/node process registered by `iwsdk/vite-plugin-dev` — so the runtime is reaped regardless. Call sites that already spawn real executables (`openUrl` → `cmd.exe`, `runReferenceCommand` → `node.exe`) are intentionally left unchanged. Note: on Windows, combining a non-empty args array with `shell: true` emits Node's benign `DEP0190` deprecation warning. It is harmless here — `spawnArgs` is a fully-controlled constant (`["run", <script-from-package.json>]`), no user input, no injection vector. Reviewed By: zjm-meta Differential Revision: D106830798 fbshipit-source-id: 311253af5ed7d0d177e062beff3163308e4d75f6
1 parent 5e9c294 commit 0da5368

2 files changed

Lines changed: 4 additions & 0 deletions

File tree

packages/cli/src/commands/dev.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,8 @@ export async function handleDevUp(
478478
detached: !foreground,
479479
stdio: foreground ? 'inherit' : ['ignore', stdoutFd, stdoutFd],
480480
env: process.env,
481+
// npm/pnpm/yarn are .cmd shims on Windows; Node cannot spawn them without a shell.
482+
shell: process.platform === 'win32',
481483
});
482484
const childExitPromise = waitForChildExit(child);
483485
let childExit: ProcessExitResult | null = null;

packages/cli/src/hzdb-telemetry.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ function hzdbTelemetry(args: string[], clientVersion?: string): void {
1414
}
1515
const child = spawn('npx', [...globalArgs, ...args], {
1616
stdio: 'ignore',
17+
// npx is a .cmd shim on Windows; Node cannot spawn it without a shell.
18+
shell: process.platform === 'win32',
1719
});
1820
child.on('error', () => {});
1921
child.unref();

0 commit comments

Comments
 (0)