refactor(security): dedupe shell env probe and add path regression test

This commit is contained in:
Peter Steinberger
2026-02-24 03:11:18 +00:00
parent 64aab80201
commit 204d9fb404
3 changed files with 100 additions and 52 deletions

View File

@@ -1,3 +1,6 @@
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import type { ExecApprovalsResolved } from "../infra/exec-approvals.js";
import { captureEnv } from "../test-utils/env.js";
@@ -67,7 +70,7 @@ describe("exec PATH login shell merge", () => {
let envSnapshot: ReturnType<typeof captureEnv>;
beforeEach(() => {
envSnapshot = captureEnv(["PATH"]);
envSnapshot = captureEnv(["PATH", "SHELL"]);
});
afterEach(() => {
@@ -112,6 +115,43 @@ describe("exec PATH login shell merge", () => {
expect(shellPathMock).not.toHaveBeenCalled();
});
it("does not apply login-shell PATH when probe rejects unregistered absolute SHELL", async () => {
if (isWin) {
return;
}
process.env.PATH = "/usr/bin";
const shellDir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-shell-env-"));
const unregisteredShellPath = path.join(shellDir, "unregistered-shell");
fs.writeFileSync(unregisteredShellPath, '#!/bin/sh\nexec /bin/sh "$@"\n', {
encoding: "utf8",
mode: 0o755,
});
process.env.SHELL = unregisteredShellPath;
try {
const shellPathMock = vi.mocked(getShellPathFromLoginShell);
shellPathMock.mockClear();
shellPathMock.mockImplementation((opts) =>
opts.env.SHELL?.trim() === unregisteredShellPath ? null : "/custom/bin:/opt/bin",
);
const tool = createExecTool({ host: "gateway", security: "full", ask: "off" });
const result = await tool.execute("call1", { command: "echo $PATH" });
const entries = normalizePathEntries(result.content.find((c) => c.type === "text")?.text);
expect(entries).toEqual(["/usr/bin"]);
expect(shellPathMock).toHaveBeenCalledTimes(1);
expect(shellPathMock).toHaveBeenCalledWith(
expect.objectContaining({
env: process.env,
timeoutMs: 1234,
}),
);
} finally {
fs.rmSync(shellDir, { recursive: true, force: true });
}
});
});
describe("exec host env validation", () => {