mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-24 19:35:28 -06:00
fix(gateway): reject unknown agent ids before resolving terminal isolation
This commit is contained in:
@@ -67,6 +67,14 @@ export const terminalHandlers: GatewayRequestHandlers = {
|
||||
respond(false, undefined, errorShape(ErrorCodes.UNAVAILABLE, "terminal is disabled"));
|
||||
return;
|
||||
}
|
||||
if (launch.block.kind === "unknown-agent") {
|
||||
respond(
|
||||
false,
|
||||
undefined,
|
||||
errorShape(ErrorCodes.INVALID_REQUEST, `unknown agent "${launch.block.agentId}"`),
|
||||
);
|
||||
return;
|
||||
}
|
||||
// Fail closed: a sandboxed agent must never receive a host shell.
|
||||
respond(
|
||||
false,
|
||||
|
||||
@@ -90,6 +90,45 @@ describe("resolveTerminalLaunch", () => {
|
||||
expect(result.plan.cwd).toBe(workspace);
|
||||
}
|
||||
});
|
||||
|
||||
it("fails closed for an unknown explicit agent id", () => {
|
||||
// Every configured agent is fully sandboxed; an unknown id must not fall
|
||||
// through to the (unsandboxed) global defaults and a host-home shell.
|
||||
const config = {
|
||||
agents: {
|
||||
list: [{ id: "locked", sandbox: { mode: "all" } }],
|
||||
},
|
||||
} as unknown as OpenClawConfig;
|
||||
const result = resolveTerminalLaunch({
|
||||
config,
|
||||
enabled: true,
|
||||
agentId: "ghost",
|
||||
env: { SHELL: "/bin/zsh" },
|
||||
platform: "linux",
|
||||
});
|
||||
expect(result).toEqual({ ok: false, block: { kind: "unknown-agent", agentId: "ghost" } });
|
||||
});
|
||||
|
||||
it("accepts an explicit id that names a configured agent", () => {
|
||||
const workspace = mkdtempSync(path.join(os.tmpdir(), "term-ws-id-"));
|
||||
const config = {
|
||||
agents: {
|
||||
defaults: { workspace },
|
||||
list: [{ id: "Ops" }],
|
||||
},
|
||||
} as unknown as OpenClawConfig;
|
||||
const result = resolveTerminalLaunch({
|
||||
config,
|
||||
enabled: true,
|
||||
agentId: "ops",
|
||||
env: { SHELL: "/bin/zsh" },
|
||||
platform: "linux",
|
||||
});
|
||||
expect(result.ok).toBe(true);
|
||||
if (result.ok) {
|
||||
expect(result.plan.agentId).toBe("ops");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("buildTerminalEnv", () => {
|
||||
|
||||
@@ -4,15 +4,18 @@ import { existsSync, statSync } from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import {
|
||||
listAgentIds,
|
||||
resolveAgentWorkspaceDir,
|
||||
resolveDefaultAgentId,
|
||||
} from "../../agents/agent-scope-config.js";
|
||||
import { resolveSandboxConfigForAgent } from "../../agents/sandbox/config.js";
|
||||
import type { OpenClawConfig } from "../../config/types.openclaw.js";
|
||||
import { normalizeAgentId } from "../../routing/session-key.js";
|
||||
|
||||
/** Why a terminal cannot open, or `null` when it can. */
|
||||
export type TerminalLaunchBlock =
|
||||
| { kind: "disabled" }
|
||||
| { kind: "unknown-agent"; agentId: string }
|
||||
| { kind: "sandboxed"; agentId: string; mode: "all" };
|
||||
|
||||
/** Resolved plan for a host terminal session. */
|
||||
@@ -73,7 +76,14 @@ export function resolveTerminalLaunch(params: {
|
||||
return { ok: false, block: { kind: "disabled" } };
|
||||
}
|
||||
const env = params.env ?? process.env;
|
||||
const agentId = params.agentId?.trim() || resolveDefaultAgentId(params.config);
|
||||
const requested = params.agentId?.trim();
|
||||
const agentId = requested ? normalizeAgentId(requested) : resolveDefaultAgentId(params.config);
|
||||
// Fail closed on unknown ids: they would resolve against the *global*
|
||||
// sandbox defaults and an invented workspace, sidestepping a per-agent
|
||||
// `sandbox.mode: "all"` refusal below.
|
||||
if (requested && !listAgentIds(params.config).includes(agentId)) {
|
||||
return { ok: false, block: { kind: "unknown-agent", agentId } };
|
||||
}
|
||||
const sandbox = resolveSandboxConfigForAgent(params.config, agentId);
|
||||
// Only "all" sandboxes every session. Under "non-main" the agent's main
|
||||
// session still runs on the host, so a host terminal there is consistent with
|
||||
|
||||
Reference in New Issue
Block a user