mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-09 16:00:43 +00:00
Use the shared Windows cmd.exe command-line builder for `.cmd` and `.bat` UI runner launches so Node.js v24 no longer sees `spawn(file, args, { shell: true })` and emits DEP0190.
The launcher keeps ordinary `.exe`/`.com` and non-Windows paths on direct argv spawning, while Windows command scripts now run through `cmd.exe /d /s /c` with `shell: false` and `windowsVerbatimArguments: true`.
Local and CI verification passed, including focused UI runner tests, build, check, Real behavior proof, and ClawSweeper gates.
Co-authored-by: Nandana Dileep <nandanadileep@users.noreply.github.com>
Co-authored-by: Brad Groux <3053586+BradGroux@users.noreply.github.com>
92 lines
2.8 KiB
TypeScript
92 lines
2.8 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { resolveSpawnCall, shouldUseCmdExeForCommand } from "../../scripts/ui.js";
|
|
|
|
describe("scripts/ui windows spawn behavior", () => {
|
|
it("wraps Windows command launchers with cmd.exe without enabling shell mode", () => {
|
|
expect(
|
|
shouldUseCmdExeForCommand("C:\\Users\\dev\\AppData\\Local\\pnpm\\pnpm.CMD", "win32"),
|
|
).toBe(true);
|
|
|
|
expect(
|
|
resolveSpawnCall(
|
|
"C:\\Program Files\\nodejs\\pnpm.cmd",
|
|
["run", "build", "-t", "path with spaces"],
|
|
{ PATH: "C:\\bin" },
|
|
{ comSpec: "C:\\Windows\\System32\\cmd.exe", cwd: "C:\\repo\\ui", platform: "win32" },
|
|
),
|
|
).toEqual({
|
|
command: "C:\\Windows\\System32\\cmd.exe",
|
|
args: [
|
|
"/d",
|
|
"/s",
|
|
"/c",
|
|
'"C:\\Program Files\\nodejs\\pnpm.cmd" run build -t "path with spaces"',
|
|
],
|
|
options: {
|
|
cwd: "C:\\repo\\ui",
|
|
stdio: "inherit",
|
|
env: { PATH: "C:\\bin" },
|
|
shell: false,
|
|
windowsVerbatimArguments: true,
|
|
},
|
|
});
|
|
});
|
|
|
|
it("does not use cmd.exe for non-command launchers", () => {
|
|
expect(shouldUseCmdExeForCommand("C:\\Program Files\\nodejs\\node.exe", "win32")).toBe(false);
|
|
expect(shouldUseCmdExeForCommand("C:\\tools\\pnpm.com", "win32")).toBe(false);
|
|
expect(shouldUseCmdExeForCommand("/usr/local/bin/pnpm", "linux")).toBe(false);
|
|
|
|
expect(
|
|
resolveSpawnCall(
|
|
"C:\\Program Files\\nodejs\\pnpm.exe",
|
|
["run", "build"],
|
|
{ PATH: "C:\\bin" },
|
|
{ cwd: "C:\\repo\\ui", platform: "win32" },
|
|
),
|
|
).toEqual({
|
|
command: "C:\\Program Files\\nodejs\\pnpm.exe",
|
|
args: ["run", "build"],
|
|
options: {
|
|
cwd: "C:\\repo\\ui",
|
|
stdio: "inherit",
|
|
env: { PATH: "C:\\bin" },
|
|
shell: false,
|
|
},
|
|
});
|
|
});
|
|
|
|
it("rejects unsafe cmd.exe arguments before launch", () => {
|
|
expect(() =>
|
|
resolveSpawnCall("C:\\tools\\pnpm.cmd", ["run", "build", "evil&calc"], undefined, {
|
|
platform: "win32",
|
|
}),
|
|
).toThrow(/unsafe windows cmd\.exe argument/i);
|
|
expect(() =>
|
|
resolveSpawnCall("C:\\tools\\pnpm.cmd", ["run", "build", "%PATH%"], undefined, {
|
|
platform: "win32",
|
|
}),
|
|
).toThrow(/unsafe windows cmd\.exe argument/i);
|
|
});
|
|
|
|
it("keeps non-Windows launches direct even with shell metacharacters", () => {
|
|
expect(
|
|
resolveSpawnCall(
|
|
"/usr/local/bin/pnpm",
|
|
["run", "build", "contains&metacharacters"],
|
|
{ PATH: "/bin" },
|
|
{ cwd: "/repo/ui", platform: "linux" },
|
|
),
|
|
).toEqual({
|
|
command: "/usr/local/bin/pnpm",
|
|
args: ["run", "build", "contains&metacharacters"],
|
|
options: {
|
|
cwd: "/repo/ui",
|
|
stdio: "inherit",
|
|
env: { PATH: "/bin" },
|
|
shell: false,
|
|
},
|
|
});
|
|
});
|
|
});
|