



























@@ -1,49 +1,91 @@
11import { describe, expect, it } from "vitest";
2-import {
3-assertSafeWindowsShellArgs,
4-prepareSpawnCommand,
5-shouldUseShellForCommand,
6-} from "../../scripts/ui.js";
2+import { resolveSpawnCall, shouldUseCmdExeForCommand } from "../../scripts/ui.js";
7384describe("scripts/ui windows spawn behavior", () => {
9-it("enables shell for Windows command launchers that require cmd.exe", () => {
5+it("wraps Windows command launchers with cmd.exe without enabling shell mode", () => {
106expect(
11-shouldUseShellForCommand("C:\\Users\\dev\\AppData\\Local\\pnpm\\pnpm.CMD", "win32"),
7+shouldUseCmdExeForCommand("C:\\Users\\dev\\AppData\\Local\\pnpm\\pnpm.CMD", "win32"),
128).toBe(true);
13-expect(shouldUseShellForCommand("C:\\tools\\pnpm.bat", "win32")).toBe(true);
14-});
15916-it("does not enable shell for non-shell launchers", () => {
17-expect(shouldUseShellForCommand("C:\\Program Files\\nodejs\\node.exe", "win32")).toBe(false);
18-expect(shouldUseShellForCommand("/usr/local/bin/pnpm", "linux")).toBe(false);
10+expect(
11+resolveSpawnCall(
12+"C:\\Program Files\\nodejs\\pnpm.cmd",
13+["run", "build", "-t", "path with spaces"],
14+{ PATH: "C:\\bin" },
15+{ comSpec: "C:\\Windows\\System32\\cmd.exe", cwd: "C:\\repo\\ui", platform: "win32" },
16+),
17+).toEqual({
18+command: "C:\\Windows\\System32\\cmd.exe",
19+args: [
20+"/d",
21+"/s",
22+"/c",
23+'"C:\\Program Files\\nodejs\\pnpm.cmd" run build -t "path with spaces"',
24+],
25+options: {
26+cwd: "C:\\repo\\ui",
27+stdio: "inherit",
28+env: { PATH: "C:\\bin" },
29+shell: false,
30+windowsVerbatimArguments: true,
31+},
32+});
1933});
203421-it("quotes Windows shell launcher paths before passing them to spawn", () => {
22-expect(prepareSpawnCommand("C:\\Program Files\\nodejs\\pnpm.cmd", "win32")).toBe(
23-'"C:\\Program Files\\nodejs\\pnpm.cmd"',
24-);
25-expect(prepareSpawnCommand("C:\\Program Files\\nodejs\\pnpm.exe", "win32")).toBe(
26-"C:\\Program Files\\nodejs\\pnpm.exe",
27-);
28-expect(prepareSpawnCommand("/usr/local/bin/pnpm", "linux")).toBe("/usr/local/bin/pnpm");
29-});
35+it("does not use cmd.exe for non-command launchers", () => {
36+expect(shouldUseCmdExeForCommand("C:\\Program Files\\nodejs\\node.exe", "win32")).toBe(false);
37+expect(shouldUseCmdExeForCommand("C:\\tools\\pnpm.com", "win32")).toBe(false);
38+expect(shouldUseCmdExeForCommand("/usr/local/bin/pnpm", "linux")).toBe(false);
303931-it("allows safe forwarded args when shell mode is required on Windows", () => {
3240expect(
33-assertSafeWindowsShellArgs(["run", "build", "--filter", "@openclaw/ui"], "win32"),
34-).toBeUndefined();
41+resolveSpawnCall(
42+"C:\\Program Files\\nodejs\\pnpm.exe",
43+["run", "build"],
44+{ PATH: "C:\\bin" },
45+{ cwd: "C:\\repo\\ui", platform: "win32" },
46+),
47+).toEqual({
48+command: "C:\\Program Files\\nodejs\\pnpm.exe",
49+args: ["run", "build"],
50+options: {
51+cwd: "C:\\repo\\ui",
52+stdio: "inherit",
53+env: { PATH: "C:\\bin" },
54+shell: false,
55+},
56+});
3557});
365837-it("rejects dangerous forwarded args when shell mode is required on Windows", () => {
38-expect(() => assertSafeWindowsShellArgs(["run", "build", "evil&calc"], "win32")).toThrow(
39-/unsafe windows shell argument/i,
40-);
41-expect(() => assertSafeWindowsShellArgs(["run", "build", "%PATH%"], "win32")).toThrow(
42-/unsafe windows shell argument/i,
43-);
59+it("rejects unsafe cmd.exe arguments before launch", () => {
60+expect(() =>
61+resolveSpawnCall("C:\\tools\\pnpm.cmd", ["run", "build", "evil&calc"], undefined, {
62+platform: "win32",
63+}),
64+).toThrow(/unsafe windows cmd\.exe argument/i);
65+expect(() =>
66+resolveSpawnCall("C:\\tools\\pnpm.cmd", ["run", "build", "%PATH%"], undefined, {
67+platform: "win32",
68+}),
69+).toThrow(/unsafe windows cmd\.exe argument/i);
4470});
457146-it("does not reject args on non-windows platforms", () => {
47-expect(assertSafeWindowsShellArgs(["contains&metacharacters"], "linux")).toBeUndefined();
72+it("keeps non-Windows launches direct even with shell metacharacters", () => {
73+expect(
74+resolveSpawnCall(
75+"/usr/local/bin/pnpm",
76+["run", "build", "contains&metacharacters"],
77+{ PATH: "/bin" },
78+{ cwd: "/repo/ui", platform: "linux" },
79+),
80+).toEqual({
81+command: "/usr/local/bin/pnpm",
82+args: ["run", "build", "contains&metacharacters"],
83+options: {
84+cwd: "/repo/ui",
85+stdio: "inherit",
86+env: { PATH: "/bin" },
87+shell: false,
88+},
89+});
4890});
4991});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。