From 135b62cb69ec07976deef32d2f32ac4926fff9de Mon Sep 17 00:00:00 2001 From: ssdiwu <467012623@qq.com> Date: Thu, 12 Mar 2026 15:01:27 +0800 Subject: [PATCH] test(control-ui): cover IPv6 loopback token scope --- ui/src/ui/storage.node.test.ts | 42 ++++++++++++++++++++++++++++++++++ ui/src/ui/storage.ts | 6 +---- 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/ui/src/ui/storage.node.test.ts b/ui/src/ui/storage.node.test.ts index 710d96ec963..88dffd6cf25 100644 --- a/ui/src/ui/storage.node.test.ts +++ b/ui/src/ui/storage.node.test.ts @@ -249,6 +249,48 @@ describe("loadSettings default gateway URL derivation", () => { }); }); + it("reuses a session token across IPv6 and IPv4 loopback aliases", async () => { + setTestLocation({ + protocol: "http:", + host: "[::1]:18789", + pathname: "/", + }); + + const { loadSettings, saveSettings } = await import("./storage.ts"); + saveSettings({ + gatewayUrl: "ws://[::1]:18789", + token: "loopback-token", + sessionKey: "main", + lastActiveSessionKey: "main", + theme: "system", + chatFocusMode: false, + chatShowThinking: true, + splitRatio: 0.6, + navCollapsed: false, + navGroupsCollapsed: {}, + }); + + localStorage.setItem( + "openclaw.control.settings.v1", + JSON.stringify({ + gatewayUrl: "ws://127.0.0.1:18789", + sessionKey: "main", + lastActiveSessionKey: "main", + theme: "system", + chatFocusMode: false, + chatShowThinking: true, + splitRatio: 0.6, + navCollapsed: false, + navGroupsCollapsed: {}, + }), + ); + + expect(loadSettings()).toMatchObject({ + gatewayUrl: "ws://127.0.0.1:18789", + token: "loopback-token", + }); + }); + it("does not reuse a loopback token across different ports", async () => { setTestLocation({ protocol: "http:", diff --git a/ui/src/ui/storage.ts b/ui/src/ui/storage.ts index 6dbe70c9ab3..0240df0cd59 100644 --- a/ui/src/ui/storage.ts +++ b/ui/src/ui/storage.ts @@ -45,11 +45,7 @@ function normalizeGatewayTokenScope(gatewayUrl: string): string { const parsed = base ? new URL(trimmed, base) : new URL(trimmed); const host = parsed.hostname.trim().toLowerCase(); const isLoopbackHost = - host === "localhost" || - host === "127.0.0.1" || - host === "::1" || - host === "[::1]" || - host.startsWith("127."); + host === "localhost" || host === "127.0.0.1" || host === "[::1]" || host.startsWith("127."); const pathname = parsed.pathname === "/" ? "" : parsed.pathname.replace(/\/+$/, "") || parsed.pathname; const hostPort = isLoopbackHost