mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-23 10:55:31 -06:00
008f04a656
* feat(mxc): add Windows MXC sandbox backend Add the official MXC sandbox plugin package with Windows ProcessContainer execution, plugin-owned MXC SDK dependency packaging, host-backed filesystem bridge support, and configured MXC policy file loading via mxcPolicyPaths. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(mxc): preserve Windows binary override paths * fix: remove stray sandbox barrel export Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9ea19539-b8ca-44fb-93bd-b8496e3deb2c * fix(mxc): address sandbox review feedback Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * fix(mxc): satisfy test type checks Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * fix(mxc): clarify protected skill enforcement Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * test(mxc): align fail-closed expectations Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * fix(mxc): satisfy extension lint Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * fix(plugin-sdk): narrow fs-safe remove surface Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * fix(mxc): repair rebased CI failures * fix(scripts): declare shrinkwrap override normalizer --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Gio Della-Libera <235387111+giodl73-repo@users.noreply.github.com> Co-authored-by: Dallin Romney <dallinromney@gmail.com>
120 lines
3.6 KiB
TypeScript
120 lines
3.6 KiB
TypeScript
// Windows process environment helpers for the MXC ProcessContainer backend.
|
|
//
|
|
// MXC's BaseContainerRunner treats a non-empty `process.env` as a replacement
|
|
// environment block for CreateProcessInSandbox: when present it replaces the
|
|
// entire default OS environment, so any required OS var (SystemRoot, COMSPEC, …)
|
|
// that is not listed is missing and cmd.exe fails with ERROR_ENVVAR_NOT_FOUND.
|
|
// These helpers build a minimal-but-complete Windows env block from required OS
|
|
// defaults plus caller overrides, and a separate launcher env for the spawn
|
|
// process itself.
|
|
|
|
// Env vars required by cmd.exe / CreateProcess inside the AppContainer. Caller
|
|
// overrides are layered on top; nothing else from the host environment leaks in.
|
|
const WINDOWS_PROCESS_ENV_DEFAULT_KEYS = [
|
|
"SystemRoot",
|
|
"SystemDrive",
|
|
"ComSpec",
|
|
"WINDIR",
|
|
"PATH",
|
|
"PATHEXT",
|
|
"TEMP",
|
|
"TMP",
|
|
"USERPROFILE",
|
|
"APPDATA",
|
|
"LOCALAPPDATA",
|
|
"ProgramData",
|
|
"ALLUSERSPROFILE",
|
|
"ProgramFiles",
|
|
"ProgramFiles(x86)",
|
|
"ProgramW6432",
|
|
"CommonProgramFiles",
|
|
"CommonProgramFiles(x86)",
|
|
"CommonProgramW6432",
|
|
"PUBLIC",
|
|
"HOMEDRIVE",
|
|
"HOMEPATH",
|
|
"USERNAME",
|
|
"USERDOMAIN",
|
|
"COMPUTERNAME",
|
|
"OS",
|
|
"PROCESSOR_ARCHITECTURE",
|
|
"PROCESSOR_IDENTIFIER",
|
|
"PROCESSOR_LEVEL",
|
|
"PROCESSOR_REVISION",
|
|
"NUMBER_OF_PROCESSORS",
|
|
] as const;
|
|
|
|
// Env vars forwarded to the plugin-side Node launcher process (not the sandboxed
|
|
// child). The launcher only needs enough OS context to locate Node, temp dirs,
|
|
// and the user profile; the sandbox policy itself travels via the JSON payload.
|
|
const LAUNCHER_ENV_KEYS = [
|
|
"SystemRoot",
|
|
"SystemDrive",
|
|
"ComSpec",
|
|
"WINDIR",
|
|
"PATH",
|
|
"PATHEXT",
|
|
"TEMP",
|
|
"TMP",
|
|
"USERPROFILE",
|
|
"APPDATA",
|
|
"LOCALAPPDATA",
|
|
"ProgramFiles",
|
|
"ProgramFiles(x86)",
|
|
"ProgramW6432",
|
|
] as const;
|
|
|
|
function getEnvValueCaseInsensitive(env: NodeJS.ProcessEnv, key: string): string | undefined {
|
|
const exact = env[key];
|
|
if (exact !== undefined) {
|
|
return exact;
|
|
}
|
|
const normalizedKey = key.toLowerCase();
|
|
const match = Object.entries(env).find(
|
|
([candidate]) => candidate.toLowerCase() === normalizedKey,
|
|
);
|
|
return match?.[1];
|
|
}
|
|
|
|
function setCaseInsensitiveEnvEntry(
|
|
entries: Map<string, { key: string; value: string }>,
|
|
key: string,
|
|
value: string | undefined,
|
|
): void {
|
|
if (!key || key.includes("=") || value === undefined) {
|
|
return;
|
|
}
|
|
entries.set(key.toLowerCase(), { key, value });
|
|
}
|
|
|
|
// Build the Windows replacement env block: required OS defaults first, then
|
|
// caller overrides (case-insensitively, since Windows env names are
|
|
// case-insensitive). Keys containing `=` are dropped so a malicious caller key
|
|
// cannot inject extra `NAME=VALUE` pairs into the block.
|
|
export function normalizeWindowsProcessEnvRecord(
|
|
callerEnv: Record<string, string>,
|
|
hostEnv: NodeJS.ProcessEnv = process.env,
|
|
): string[] {
|
|
const entries = new Map<string, { key: string; value: string }>();
|
|
for (const key of WINDOWS_PROCESS_ENV_DEFAULT_KEYS) {
|
|
setCaseInsensitiveEnvEntry(entries, key, getEnvValueCaseInsensitive(hostEnv, key));
|
|
}
|
|
for (const [key, value] of Object.entries(callerEnv)) {
|
|
setCaseInsensitiveEnvEntry(entries, key, value);
|
|
}
|
|
return [...entries.values()]
|
|
.toSorted((a, b) => a.key.localeCompare(b.key))
|
|
.map(({ key, value }) => `${key}=${value}`);
|
|
}
|
|
|
|
export function buildLauncherEnv(hostEnv: NodeJS.ProcessEnv = process.env): NodeJS.ProcessEnv {
|
|
const env: NodeJS.ProcessEnv = {};
|
|
for (const key of LAUNCHER_ENV_KEYS) {
|
|
const value = getEnvValueCaseInsensitive(hostEnv, key);
|
|
if (value !== undefined) {
|
|
env[key] = value;
|
|
}
|
|
}
|
|
return env;
|
|
}
|