fix(exec): keep implicit sandbox default and restore no-alert baseline

This commit is contained in:
Peter Steinberger
2026-02-23 02:17:43 +01:00
parent f6c2e99f5d
commit 45febecf2a
4 changed files with 29 additions and 8 deletions

View File

@@ -1,6 +1,6 @@
{
"name": "openclaw",
"version": "2026.2.22-1",
"version": "2026.2.22-2",
"description": "Multi-channel AI gateway with extensible messaging integrations",
"keywords": [],
"homepage": "https://github.com/openclaw/openclaw#readme",

View File

@@ -604,6 +604,31 @@ describe("Agent-specific tool filtering", () => {
expect(resultDetails?.status).toBe("completed");
});
it("keeps sandbox as the implicit exec host default without forcing gateway approvals", async () => {
const tools = createOpenClawCodingTools({
config: {},
sessionKey: "agent:main:main",
workspaceDir: "/tmp/test-main-implicit-sandbox",
agentDir: "/tmp/agent-main-implicit-sandbox",
});
const execTool = tools.find((tool) => tool.name === "exec");
expect(execTool).toBeDefined();
const result = await execTool!.execute("call-implicit-sandbox-default", {
command: "echo done",
yieldMs: 10,
});
const details = result?.details as { status?: string } | undefined;
expect(details?.status).toBe("completed");
await expect(
execTool!.execute("call-implicit-sandbox-gateway", {
command: "echo done",
host: "gateway",
}),
).rejects.toThrow("exec host not allowed");
});
it("fails closed when exec host=sandbox is requested without sandbox runtime", async () => {
const tools = createOpenClawCodingTools({
config: {},
@@ -618,7 +643,7 @@ describe("Agent-specific tool filtering", () => {
command: "echo done",
host: "sandbox",
}),
).rejects.toThrow("exec host not allowed");
).rejects.toThrow("exec host=sandbox is configured");
});
it("should apply agent-specific exec host defaults over global defaults", async () => {

View File

@@ -364,13 +364,9 @@ export function createOpenClawCodingTools(options?: {
return [tool];
});
const { cleanupMs: cleanupMsOverride, ...execDefaults } = options?.exec ?? {};
// Fail-closed baseline: when no sandbox context exists, default exec to gateway
// so we never silently treat "sandbox" as host execution.
const resolvedExecHost =
options?.exec?.host ?? execConfig.host ?? (sandbox ? "sandbox" : "gateway");
const execTool = createExecTool({
...execDefaults,
host: resolvedExecHost,
host: options?.exec?.host ?? execConfig.host,
security: options?.exec?.security ?? execConfig.security,
ask: options?.exec?.ask ?? execConfig.ask,
node: options?.exec?.node ?? execConfig.node,

View File

@@ -215,7 +215,7 @@ export function parseToolsBySenderTypedKey(
export type GroupToolPolicyBySenderConfig = Record<string, GroupToolPolicyConfig>;
export type ExecToolConfig = {
/** Exec host routing (default: sandbox with sandbox runtime, otherwise gateway). */
/** Exec host routing (default: sandbox). */
host?: "sandbox" | "gateway" | "node";
/** Exec security mode (default: deny). */
security?: "deny" | "allowlist" | "full";