mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 14:20:44 +00:00
fix: block SystemRoot/WINDIR in workspace .env and harden reg.exe path resolution [AI-assisted] (#74454)
* fix: address issue * fix: address PR review feedback * Add changelog entry for PR #74454 --------- Co-authored-by: Devin Robison <drobison@nvidia.com>
This commit is contained in:
@@ -228,8 +228,10 @@ describe("loadDotEnv", () => {
|
||||
"HTTP_PROXY=http://evil-proxy:8080",
|
||||
"HOMEBREW_BREW_FILE=./evil-brew/bin/brew",
|
||||
"HOMEBREW_PREFIX=./evil-brew",
|
||||
"SystemRoot=.\\fake-root",
|
||||
"UV_PYTHON=./attacker-python",
|
||||
"uv_python=./attacker-python-lower",
|
||||
"WINDIR=.\\fake-windir",
|
||||
].join("\n"),
|
||||
);
|
||||
await writeEnvFile(path.join(stateDir, ".env"), "BAR=from-global\n");
|
||||
@@ -245,8 +247,10 @@ describe("loadDotEnv", () => {
|
||||
delete process.env.HTTP_PROXY;
|
||||
delete process.env.HOMEBREW_BREW_FILE;
|
||||
delete process.env.HOMEBREW_PREFIX;
|
||||
delete process.env.SystemRoot;
|
||||
delete process.env.UV_PYTHON;
|
||||
delete process.env.uv_python;
|
||||
delete process.env.WINDIR;
|
||||
|
||||
loadDotEnv({ quiet: true });
|
||||
|
||||
@@ -262,8 +266,10 @@ describe("loadDotEnv", () => {
|
||||
expect(process.env.HTTP_PROXY).toBeUndefined();
|
||||
expect(process.env.HOMEBREW_BREW_FILE).toBeUndefined();
|
||||
expect(process.env.HOMEBREW_PREFIX).toBeUndefined();
|
||||
expect(process.env.SystemRoot).toBeUndefined();
|
||||
expect(process.env.UV_PYTHON).toBeUndefined();
|
||||
expect(process.env.uv_python).toBeUndefined();
|
||||
expect(process.env.WINDIR).toBeUndefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -171,25 +171,25 @@ describe("getWindowsProgramFilesRoots", () => {
|
||||
});
|
||||
|
||||
describe("locateWindowsRegExe", () => {
|
||||
it("prefers SystemRoot and WINDIR candidates over arbitrary drive scans", () => {
|
||||
expect(
|
||||
_private.getWindowsRegExeCandidates({
|
||||
SystemRoot: "D:\\Windows",
|
||||
WINDIR: "E:\\Windows",
|
||||
}),
|
||||
).toEqual([
|
||||
"D:\\Windows\\System32\\reg.exe",
|
||||
"E:\\Windows\\System32\\reg.exe",
|
||||
"C:\\Windows\\System32\\reg.exe",
|
||||
]);
|
||||
it("uses the fixed Windows system reg.exe candidate", () => {
|
||||
expect(_private.getWindowsRegExeCandidates()).toEqual(["C:\\Windows\\System32\\reg.exe"]);
|
||||
});
|
||||
|
||||
it("dedupes equivalent roots case-insensitively", () => {
|
||||
expect(
|
||||
_private.getWindowsRegExeCandidates({
|
||||
SystemRoot: "D:\\Windows\\",
|
||||
windir: "d:\\windows",
|
||||
}),
|
||||
).toEqual(["D:\\Windows\\System32\\reg.exe", "C:\\Windows\\System32\\reg.exe"]);
|
||||
it("does not resolve readable reg.exe files from env-derived roots", () => {
|
||||
_resetWindowsInstallRootsForTests({
|
||||
isReadableFile: (filePath) => filePath === "D:\\Windows\\System32\\reg.exe",
|
||||
});
|
||||
|
||||
const originalEnv = process.env;
|
||||
try {
|
||||
process.env = {
|
||||
...originalEnv,
|
||||
SystemRoot: "D:\\Windows",
|
||||
WINDIR: "E:\\Windows",
|
||||
};
|
||||
expect(_private.locateWindowsRegExe()).toBeNull();
|
||||
} finally {
|
||||
process.env = originalEnv;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -92,29 +92,12 @@ function getEnvValueCaseInsensitive(
|
||||
return actualKey ? env[actualKey] : undefined;
|
||||
}
|
||||
|
||||
function getWindowsRegExeCandidates(env: Record<string, string | undefined>): readonly string[] {
|
||||
const seen = new Set<string>();
|
||||
const candidates: string[] = [];
|
||||
for (const root of [
|
||||
normalizeWindowsInstallRoot(getEnvValueCaseInsensitive(env, "SystemRoot")),
|
||||
normalizeWindowsInstallRoot(getEnvValueCaseInsensitive(env, "WINDIR")),
|
||||
DEFAULT_WINDOWS_SYSTEM_ROOT,
|
||||
]) {
|
||||
if (!root) {
|
||||
continue;
|
||||
}
|
||||
const key = normalizeLowercaseStringOrEmpty(root);
|
||||
if (seen.has(key)) {
|
||||
continue;
|
||||
}
|
||||
seen.add(key);
|
||||
candidates.push(path.win32.join(root, "System32", "reg.exe"));
|
||||
}
|
||||
return candidates;
|
||||
function getWindowsRegExeCandidates(): readonly string[] {
|
||||
return [path.win32.join(DEFAULT_WINDOWS_SYSTEM_ROOT, "System32", "reg.exe")];
|
||||
}
|
||||
|
||||
function locateWindowsRegExe(env: Record<string, string | undefined> = process.env): string | null {
|
||||
for (const candidate of getWindowsRegExeCandidates(env)) {
|
||||
function locateWindowsRegExe(): string | null {
|
||||
for (const candidate of getWindowsRegExeCandidates()) {
|
||||
if (isReadableFileFn(candidate)) {
|
||||
return candidate;
|
||||
}
|
||||
@@ -151,7 +134,7 @@ function runRegQuery(
|
||||
}
|
||||
|
||||
function defaultQueryRegistryValue(key: string, valueName: string): string | null {
|
||||
const regExe = locateWindowsRegExe(process.env);
|
||||
const regExe = locateWindowsRegExe();
|
||||
if (!regExe) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user