mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-24 11:25:50 -06:00
fix(infra): share trusted Windows process argv lookup
This commit is contained in:
@@ -14,7 +14,8 @@ import { z } from "zod";
|
||||
import { resolveConfigPath, resolveGatewayLockDir, resolveStateDir } from "../config/paths.js";
|
||||
import { isPidAlive } from "../shared/pid-alive.js";
|
||||
import { safeParseJsonWithSchema } from "../utils/zod-parse.js";
|
||||
import { isGatewayArgv, parseProcCmdline, parseWindowsCmdline } from "./gateway-process-argv.js";
|
||||
import { isGatewayArgv, parseProcCmdline } from "./gateway-process-argv.js";
|
||||
import { readWindowsProcessArgsSync } from "./windows-port-pids.js";
|
||||
|
||||
const DEFAULT_TIMEOUT_MS = 5000;
|
||||
const DEFAULT_POLL_INTERVAL_MS = 100;
|
||||
@@ -79,32 +80,8 @@ function readLinuxCmdline(pid: number): string[] | null {
|
||||
|
||||
const CMDLINE_EXEC_TIMEOUT_MS = 1000;
|
||||
|
||||
/**
|
||||
* Read the command line of a Windows process via `wmic`.
|
||||
* Returns an argv-style array, or null when the lookup fails (process gone,
|
||||
* `wmic` missing/deprecated, timeout, etc.).
|
||||
*/
|
||||
function readWindowsCmdline(pid: number): string[] | null {
|
||||
try {
|
||||
// Omit `encoding` so execFileSync returns a Buffer — wmic emits UTF-16LE
|
||||
// (with BOM) on most Windows 10/11 builds, which would be garbled as UTF-8.
|
||||
const buf = execFileSync(
|
||||
"wmic",
|
||||
["process", "where", `processid=${pid}`, "get", "CommandLine", "/value"],
|
||||
{ timeout: CMDLINE_EXEC_TIMEOUT_MS, windowsHide: true, stdio: ["ignore", "pipe", "ignore"] },
|
||||
) as Buffer;
|
||||
const raw =
|
||||
buf.length >= 2 && buf[0] === 0xff && buf[1] === 0xfe
|
||||
? buf.toString("utf16le")
|
||||
: buf.toString("utf8");
|
||||
const match = raw.match(/CommandLine=(.+)/);
|
||||
if (!match) {
|
||||
return null;
|
||||
}
|
||||
return parseWindowsCmdline(match[1].trim());
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
return readWindowsProcessArgsSync(pid, CMDLINE_EXEC_TIMEOUT_MS);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -140,6 +140,26 @@ describe("gateway-processes", () => {
|
||||
expect(parseCmdScriptCommandLineMock).toHaveBeenCalledWith("node.exe gateway run");
|
||||
});
|
||||
|
||||
it("decodes UTF-16 WMIC output when reading windows process args", () => {
|
||||
setPlatform("win32");
|
||||
spawnSyncMock
|
||||
.mockReturnValueOnce({
|
||||
error: new Error("powershell missing"),
|
||||
status: null,
|
||||
stdout: "",
|
||||
})
|
||||
.mockReturnValueOnce({
|
||||
error: null,
|
||||
status: 0,
|
||||
stdout: Buffer.from("\uFEFFCommandLine=node.exe gateway run\r\n", "utf16le"),
|
||||
});
|
||||
parseCmdScriptCommandLineMock.mockReturnValue(["node.exe", "gateway", "run"]);
|
||||
|
||||
expect(readGatewayProcessArgsSync(77)).toEqual(["node.exe", "gateway", "run"]);
|
||||
expect(spawnSyncMock.mock.calls[1]?.[0]).toBe(getWindowsWmicExePath());
|
||||
expect(parseCmdScriptCommandLineMock).toHaveBeenCalledWith("node.exe gateway run");
|
||||
});
|
||||
|
||||
it("signals only verified gateway processes", () => {
|
||||
setPlatform("linux");
|
||||
readFileSyncMock.mockReturnValue("node\0gateway\0");
|
||||
|
||||
@@ -95,8 +95,17 @@ export function readWindowsListeningPidsResultSync(
|
||||
// Windows process-args reading (PowerShell → WMIC fallback)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function extractWindowsCommandLine(raw: string): string | null {
|
||||
const lines = normalizeStringEntries(raw.split(/\r?\n/));
|
||||
function decodeWindowsProcessOutput(output: Buffer | string): string {
|
||||
if (!Buffer.isBuffer(output)) {
|
||||
return output;
|
||||
}
|
||||
return output.length >= 2 && output[0] === 0xff && output[1] === 0xfe
|
||||
? output.toString("utf16le")
|
||||
: output.toString("utf8");
|
||||
}
|
||||
|
||||
function extractWindowsCommandLine(raw: Buffer | string): string | null {
|
||||
const lines = normalizeStringEntries(decodeWindowsProcessOutput(raw).split(/\r?\n/));
|
||||
for (const line of lines) {
|
||||
if (!normalizeLowercaseStringOrEmpty(line).startsWith("commandline=")) {
|
||||
continue;
|
||||
@@ -140,9 +149,9 @@ export function readWindowsProcessArgsResultSync(
|
||||
getWindowsWmicExePath(),
|
||||
["process", "where", `ProcessId=${pid}`, "get", "CommandLine", "/value"],
|
||||
{
|
||||
encoding: "utf8",
|
||||
timeout: timeoutMs,
|
||||
windowsHide: true,
|
||||
stdio: ["ignore", "pipe", "ignore"],
|
||||
},
|
||||
);
|
||||
if (!wmic.error && wmic.status === 0) {
|
||||
|
||||
Reference in New Issue
Block a user