Files
openclaw/src/agents/bash-tools.exec.security-floor.test.ts
2026-05-11 16:21:43 +01:00

114 lines
3.1 KiB
TypeScript

import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { afterEach, beforeEach, describe, expect, it } from "vitest";
import { captureEnv } from "../test-utils/env.js";
import { resetProcessRegistryForTests } from "./bash-process-registry.js";
import { createExecTool } from "./bash-tools.exec.js";
describe("exec security floor", () => {
let envSnapshot: ReturnType<typeof captureEnv>;
let tempRoot: string | undefined;
beforeEach(() => {
envSnapshot = captureEnv([
"HOME",
"USERPROFILE",
"HOMEDRIVE",
"HOMEPATH",
"OPENCLAW_HOME",
"OPENCLAW_STATE_DIR",
"SHELL",
]);
tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-exec-security-floor-"));
process.env.HOME = tempRoot;
process.env.USERPROFILE = tempRoot;
process.env.OPENCLAW_HOME = tempRoot;
process.env.OPENCLAW_STATE_DIR = path.join(tempRoot, "state");
if (process.platform === "win32") {
const parsed = path.parse(tempRoot);
process.env.HOMEDRIVE = parsed.root.slice(0, 2);
process.env.HOMEPATH = tempRoot.slice(2) || "\\";
} else {
delete process.env.HOMEDRIVE;
delete process.env.HOMEPATH;
}
resetProcessRegistryForTests();
});
afterEach(() => {
const dir = tempRoot;
tempRoot = undefined;
envSnapshot.restore();
if (dir) {
fs.rmSync(dir, { recursive: true, force: true });
}
});
it("ignores model-supplied allowlist security when configured security is full", async () => {
const tool = createExecTool({
security: "full",
ask: "off",
});
const result = await tool.execute("call-1", {
command: "echo hello",
security: "allowlist",
ask: "off",
});
expect(result.content[0]?.type).toBe("text");
const text = (result.content[0] as { text?: string }).text ?? "";
expect(text).not.toMatch(/exec denied/i);
expect(text).not.toMatch(/allowlist miss/i);
expect(text.trim()).toContain("hello");
});
it("enforces configured allowlist security when model also passes allowlist", async () => {
const tool = createExecTool({
security: "allowlist",
ask: "off",
safeBins: [],
});
await expect(
tool.execute("call-2", {
command: "echo hello",
security: "allowlist",
ask: "off",
}),
).rejects.toThrow(/exec denied: allowlist miss/i);
});
it("ignores model-supplied deny security when configured security is allowlist", async () => {
const tool = createExecTool({
security: "allowlist",
ask: "off",
safeBins: [],
});
await expect(
tool.execute("call-3", {
command: "echo hello",
security: "deny",
ask: "off",
}),
).rejects.toThrow(/exec denied: allowlist miss/i);
});
it("ignores model-supplied full security when configured security is deny", async () => {
const tool = createExecTool({
security: "deny",
ask: "off",
});
await expect(
tool.execute("call-4", {
command: "echo hello",
security: "full",
ask: "off",
}),
).rejects.toThrow(/exec denied/i);
});
});