gateway: trim control UI bootstrap payload (#57727)

This commit is contained in:
Jacob Tomlinson
2026-03-30 07:08:19 -07:00
committed by GitHub
parent 847912f3e2
commit c5c10adc02
6 changed files with 10 additions and 16 deletions

View File

@@ -4,6 +4,4 @@ export type ControlUiBootstrapConfig = {
basePath: string; basePath: string;
assistantName: string; assistantName: string;
assistantAvatar: string; assistantAvatar: string;
assistantAgentId: string;
serverVersion?: string;
}; };

View File

@@ -27,7 +27,6 @@ describe("handleControlUiHttpRequest", () => {
basePath: string; basePath: string;
assistantName: string; assistantName: string;
assistantAvatar: string; assistantAvatar: string;
assistantAgentId: string;
}; };
} }
@@ -196,7 +195,8 @@ describe("handleControlUiHttpRequest", () => {
expect(parsed.basePath).toBe(""); expect(parsed.basePath).toBe("");
expect(parsed.assistantName).toBe("</script><script>alert(1)//"); expect(parsed.assistantName).toBe("</script><script>alert(1)//");
expect(parsed.assistantAvatar).toBe("/avatar/main"); expect(parsed.assistantAvatar).toBe("/avatar/main");
expect(parsed.assistantAgentId).toBe("main"); expect(parsed).not.toHaveProperty("assistantAgentId");
expect(parsed).not.toHaveProperty("serverVersion");
}, },
}); });
}); });
@@ -222,7 +222,8 @@ describe("handleControlUiHttpRequest", () => {
expect(parsed.basePath).toBe("/openclaw"); expect(parsed.basePath).toBe("/openclaw");
expect(parsed.assistantName).toBe("Ops"); expect(parsed.assistantName).toBe("Ops");
expect(parsed.assistantAvatar).toBe("/openclaw/avatar/main"); expect(parsed.assistantAvatar).toBe("/openclaw/avatar/main");
expect(parsed.assistantAgentId).toBe("main"); expect(parsed).not.toHaveProperty("assistantAgentId");
expect(parsed).not.toHaveProperty("serverVersion");
}, },
}); });
}); });

View File

@@ -10,7 +10,6 @@ import {
import { isWithinDir } from "../infra/path-safety.js"; import { isWithinDir } from "../infra/path-safety.js";
import { openVerifiedFileSync } from "../infra/safe-open-sync.js"; import { openVerifiedFileSync } from "../infra/safe-open-sync.js";
import { AVATAR_MAX_BYTES } from "../shared/avatar-policy.js"; import { AVATAR_MAX_BYTES } from "../shared/avatar-policy.js";
import { resolveRuntimeServiceVersion } from "../version.js";
import { DEFAULT_ASSISTANT_IDENTITY, resolveAssistantIdentity } from "./assistant-identity.js"; import { DEFAULT_ASSISTANT_IDENTITY, resolveAssistantIdentity } from "./assistant-identity.js";
import { import {
CONTROL_UI_BOOTSTRAP_CONFIG_PATH, CONTROL_UI_BOOTSTRAP_CONFIG_PATH,
@@ -365,8 +364,6 @@ export function handleControlUiHttpRequest(
basePath, basePath,
assistantName: identity.name, assistantName: identity.name,
assistantAvatar: avatarValue ?? identity.avatar, assistantAvatar: avatarValue ?? identity.avatar,
assistantAgentId: identity.agentId,
serverVersion: resolveRuntimeServiceVersion(process.env),
} satisfies ControlUiBootstrapConfig); } satisfies ControlUiBootstrapConfig);
return true; return true;
} }

View File

@@ -12,8 +12,6 @@ describe("loadControlUiBootstrapConfig", () => {
basePath: "/openclaw", basePath: "/openclaw",
assistantName: "Ops", assistantName: "Ops",
assistantAvatar: "O", assistantAvatar: "O",
assistantAgentId: "main",
serverVersion: "2026.3.7",
}), }),
}); });
vi.stubGlobal("fetch", fetchMock as unknown as typeof fetch); vi.stubGlobal("fetch", fetchMock as unknown as typeof fetch);
@@ -34,8 +32,8 @@ describe("loadControlUiBootstrapConfig", () => {
); );
expect(state.assistantName).toBe("Ops"); expect(state.assistantName).toBe("Ops");
expect(state.assistantAvatar).toBe("O"); expect(state.assistantAvatar).toBe("O");
expect(state.assistantAgentId).toBe("main"); expect(state.assistantAgentId).toBeNull();
expect(state.serverVersion).toBe("2026.3.7"); expect(state.serverVersion).toBeNull();
vi.unstubAllGlobals(); vi.unstubAllGlobals();
}); });
@@ -59,6 +57,8 @@ describe("loadControlUiBootstrapConfig", () => {
expect.objectContaining({ method: "GET" }), expect.objectContaining({ method: "GET" }),
); );
expect(state.assistantName).toBe("Assistant"); expect(state.assistantName).toBe("Assistant");
expect(state.assistantAgentId).toBeNull();
expect(state.serverVersion).toBeNull();
vi.unstubAllGlobals(); vi.unstubAllGlobals();
}); });
@@ -81,6 +81,8 @@ describe("loadControlUiBootstrapConfig", () => {
`/openclaw${CONTROL_UI_BOOTSTRAP_CONFIG_PATH}`, `/openclaw${CONTROL_UI_BOOTSTRAP_CONFIG_PATH}`,
expect.objectContaining({ method: "GET" }), expect.objectContaining({ method: "GET" }),
); );
expect(state.assistantAgentId).toBeNull();
expect(state.serverVersion).toBeNull();
vi.unstubAllGlobals(); vi.unstubAllGlobals();
}); });

View File

@@ -37,14 +37,11 @@ export async function loadControlUiBootstrapConfig(state: ControlUiBootstrapStat
} }
const parsed = (await res.json()) as ControlUiBootstrapConfig; const parsed = (await res.json()) as ControlUiBootstrapConfig;
const normalized = normalizeAssistantIdentity({ const normalized = normalizeAssistantIdentity({
agentId: parsed.assistantAgentId ?? null,
name: parsed.assistantName, name: parsed.assistantName,
avatar: parsed.assistantAvatar ?? null, avatar: parsed.assistantAvatar ?? null,
}); });
state.assistantName = normalized.name; state.assistantName = normalized.name;
state.assistantAvatar = normalized.avatar; state.assistantAvatar = normalized.avatar;
state.assistantAgentId = normalized.agentId ?? null;
state.serverVersion = parsed.serverVersion ?? null;
} catch { } catch {
// Ignore bootstrap failures; UI will update identity after connecting. // Ignore bootstrap failures; UI will update identity after connecting.
} }

View File

@@ -50,7 +50,6 @@ export default defineConfig(() => {
basePath: "/", basePath: "/",
assistantName: "", assistantName: "",
assistantAvatar: "", assistantAvatar: "",
assistantAgentId: "",
}), }),
); );
}); });