fix(exec): ignore malformed drive-less windows exec paths

This commit is contained in:
SnowSky1
2026-04-01 11:21:47 +08:00
committed by Peter Steinberger
parent a26f4d0f3e
commit e6ce31eb54
4 changed files with 43 additions and 0 deletions

View File

@@ -9,6 +9,7 @@ import {
parseExecArgvToken,
resolveCommandResolution,
resolveCommandResolutionFromArgv,
resolveAllowlistCandidatePath,
resolveExecutionTargetCandidatePath,
resolvePolicyTargetCandidatePath,
} from "./exec-approvals.js";
@@ -429,4 +430,20 @@ describe("exec-command-resolution", () => {
expect(long.inlineValue).toBe("blocked.txt");
}
});
it("does not synthesize cwd-joined allowlist candidates from drive-less windows roots", () => {
if (process.platform !== "win32") {
return;
}
expect(
resolveAllowlistCandidatePath(
{
rawExecutable: String.raw`:\Users\demo\AI\system\openclaw`,
executableName: "openclaw",
},
String.raw`C:\Users\demo\AI\system\openclaw`,
),
).toBeUndefined();
});
});

View File

@@ -45,6 +45,10 @@ function parseFirstToken(command: string): string | null {
return match ? match[0] : null;
}
function isDriveLessWindowsRootedPath(value: string): boolean {
return process.platform === "win32" && /^:[\\/]/.test(value);
}
function tryResolveRealpath(filePath: string | undefined): string | undefined {
if (!filePath) {
return undefined;
@@ -176,6 +180,9 @@ function resolveExecutableCandidatePathFromResolution(
return undefined;
}
const expanded = raw.startsWith("~") ? expandHomePrefix(raw) : raw;
if (isDriveLessWindowsRootedPath(expanded)) {
return undefined;
}
if (!expanded.includes("/") && !expanded.includes("\\")) {
return undefined;
}

View File

@@ -74,4 +74,16 @@ describe("executable path helpers", () => {
);
expect(resolveExecutablePath("~/missing-tool", { env: { HOME: homeDir } })).toBeUndefined();
});
it("does not treat drive-less rooted windows paths as cwd-relative executables", () => {
if (process.platform !== "win32") {
return;
}
expect(
resolveExecutablePath(String.raw`:\Users\demo\AI\system\openclaw\git.exe`, {
cwd: String.raw`C:\Users\demo\AI\system\openclaw`,
}),
).toBeUndefined();
});
});

View File

@@ -2,6 +2,10 @@ import fs from "node:fs";
import path from "node:path";
import { expandHomePrefix } from "./home-dir.js";
function isDriveLessWindowsRootedPath(value: string): boolean {
return process.platform === "win32" && /^:[\\/]/.test(value);
}
function resolveWindowsExecutableExtensions(
executable: string,
env: NodeJS.ProcessEnv | undefined,
@@ -86,6 +90,9 @@ export function resolveExecutablePath(
const expanded = rawExecutable.startsWith("~")
? expandHomePrefix(rawExecutable, { env: options?.env })
: rawExecutable;
if (isDriveLessWindowsRootedPath(expanded)) {
return undefined;
}
if (expanded.includes("/") || expanded.includes("\\")) {
if (path.isAbsolute(expanded)) {
return isExecutableFile(expanded) ? expanded : undefined;