fix(sandbox): prevent Windows PATH from poisoning docker exec (#13873)
* fix(sandbox): prevent Windows PATH from poisoning docker exec shell lookup On Windows hosts, `buildDockerExecArgs` passes the host PATH env var (containing Windows paths like `C:\Windows\System32`) to `docker exec -e PATH=...`. Docker uses this PATH to resolve the executable argument (`sh`), which fails because Windows paths don't exist in the Linux container — producing `exec: "sh": executable file not found in $PATH`. Two changes: - Skip PATH in the `-e` env loop (it's already handled separately via OPENCLAW_PREPEND_PATH + shell export) - Use absolute `/bin/sh` instead of bare `sh` to eliminate PATH dependency entirely Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * style: add braces around continue to satisfy linter Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(test): update assertion to match /bin/sh in buildDockerExecArgs Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -76,7 +76,7 @@ describe("buildDockerExecArgs", () => {
|
||||
tty: false,
|
||||
});
|
||||
|
||||
expect(args).toContain("sh");
|
||||
expect(args).toContain("/bin/sh");
|
||||
expect(args).toContain("-lc");
|
||||
});
|
||||
|
||||
|
||||
@@ -61,6 +61,12 @@ export function buildDockerExecArgs(params: {
|
||||
args.push("-w", params.workdir);
|
||||
}
|
||||
for (const [key, value] of Object.entries(params.env)) {
|
||||
// Skip PATH — passing a host PATH (e.g. Windows paths) via -e poisons
|
||||
// Docker's executable lookup, causing "sh: not found" on Windows hosts.
|
||||
// PATH is handled separately via OPENCLAW_PREPEND_PATH below.
|
||||
if (key === "PATH") {
|
||||
continue;
|
||||
}
|
||||
args.push("-e", `${key}=${value}`);
|
||||
}
|
||||
const hasCustomPath = typeof params.env.PATH === "string" && params.env.PATH.length > 0;
|
||||
@@ -75,7 +81,8 @@ export function buildDockerExecArgs(params: {
|
||||
const pathExport = hasCustomPath
|
||||
? 'export PATH="${OPENCLAW_PREPEND_PATH}:$PATH"; unset OPENCLAW_PREPEND_PATH; '
|
||||
: "";
|
||||
args.push(params.containerName, "sh", "-lc", `${pathExport}${params.command}`);
|
||||
// Use absolute path for sh to avoid dependency on PATH resolution during exec.
|
||||
args.push(params.containerName, "/bin/sh", "-lc", `${pathExport}${params.command}`);
|
||||
return args;
|
||||
}
|
||||
|
||||
|
||||
@@ -469,7 +469,7 @@ async function createSandboxContainer(params: {
|
||||
await execDocker(["start", name]);
|
||||
|
||||
if (cfg.setupCommand?.trim()) {
|
||||
await execDocker(["exec", "-i", name, "sh", "-lc", cfg.setupCommand]);
|
||||
await execDocker(["exec", "-i", name, "/bin/sh", "-lc", cfg.setupCommand]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user