mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-08 16:38:27 +00:00
Gateway: force loopback self-connections for local binds
This commit is contained in:
@@ -133,7 +133,7 @@ describe("callGateway url resolution", () => {
|
||||
expect(lastClientOptions?.url).toBe("ws://127.0.0.1:18800");
|
||||
});
|
||||
|
||||
it("uses tailnet IP with TLS when local bind is tailnet", async () => {
|
||||
it("uses loopback with TLS when local bind is tailnet", async () => {
|
||||
loadConfig.mockReturnValue({
|
||||
gateway: { mode: "local", bind: "tailnet", tls: { enabled: true } },
|
||||
});
|
||||
@@ -142,18 +142,20 @@ describe("callGateway url resolution", () => {
|
||||
|
||||
await callGateway({ method: "health" });
|
||||
|
||||
expect(lastClientOptions?.url).toBe("wss://100.64.0.1:18800");
|
||||
expect(lastClientOptions?.url).toBe("wss://127.0.0.1:18800");
|
||||
});
|
||||
|
||||
it("blocks ws:// to tailnet IP without TLS (CWE-319)", async () => {
|
||||
it("uses loopback without TLS when local bind is tailnet", async () => {
|
||||
loadConfig.mockReturnValue({ gateway: { mode: "local", bind: "tailnet" } });
|
||||
resolveGatewayPort.mockReturnValue(18800);
|
||||
pickPrimaryTailnetIPv4.mockReturnValue("100.64.0.1");
|
||||
|
||||
await expect(callGateway({ method: "health" })).rejects.toThrow("SECURITY ERROR");
|
||||
await callGateway({ method: "health" });
|
||||
|
||||
expect(lastClientOptions?.url).toBe("ws://127.0.0.1:18800");
|
||||
});
|
||||
|
||||
it("uses LAN IP with TLS when bind is lan", async () => {
|
||||
it("uses loopback with TLS when bind is lan", async () => {
|
||||
loadConfig.mockReturnValue({
|
||||
gateway: { mode: "local", bind: "lan", tls: { enabled: true } },
|
||||
});
|
||||
@@ -163,16 +165,18 @@ describe("callGateway url resolution", () => {
|
||||
|
||||
await callGateway({ method: "health" });
|
||||
|
||||
expect(lastClientOptions?.url).toBe("wss://192.168.1.42:18800");
|
||||
expect(lastClientOptions?.url).toBe("wss://127.0.0.1:18800");
|
||||
});
|
||||
|
||||
it("blocks ws:// to LAN IP without TLS (CWE-319)", async () => {
|
||||
it("uses loopback without TLS when bind is lan", async () => {
|
||||
loadConfig.mockReturnValue({ gateway: { mode: "local", bind: "lan" } });
|
||||
resolveGatewayPort.mockReturnValue(18800);
|
||||
pickPrimaryTailnetIPv4.mockReturnValue(undefined);
|
||||
pickPrimaryLanIPv4.mockReturnValue("192.168.1.42");
|
||||
|
||||
await expect(callGateway({ method: "health" })).rejects.toThrow("SECURITY ERROR");
|
||||
await callGateway({ method: "health" });
|
||||
|
||||
expect(lastClientOptions?.url).toBe("ws://127.0.0.1:18800");
|
||||
});
|
||||
|
||||
it("falls back to loopback when bind is lan but no LAN IP found", async () => {
|
||||
@@ -270,7 +274,7 @@ describe("buildGatewayConnectionDetails", () => {
|
||||
expect(details.message).toContain("Gateway target: ws://127.0.0.1:18789");
|
||||
});
|
||||
|
||||
it("uses LAN IP with TLS and reports lan source when bind is lan", () => {
|
||||
it("uses loopback URL and loopback source when bind is lan", () => {
|
||||
loadConfig.mockReturnValue({
|
||||
gateway: { mode: "local", bind: "lan", tls: { enabled: true } },
|
||||
});
|
||||
@@ -280,12 +284,12 @@ describe("buildGatewayConnectionDetails", () => {
|
||||
|
||||
const details = buildGatewayConnectionDetails();
|
||||
|
||||
expect(details.url).toBe("wss://10.0.0.5:18800");
|
||||
expect(details.urlSource).toBe("local lan 10.0.0.5");
|
||||
expect(details.url).toBe("wss://127.0.0.1:18800");
|
||||
expect(details.urlSource).toBe("local loopback");
|
||||
expect(details.bindDetail).toBe("Bind: lan");
|
||||
});
|
||||
|
||||
it("throws for ws:// to LAN IP without TLS (CWE-319)", () => {
|
||||
it("uses loopback URL for bind=lan without TLS", () => {
|
||||
loadConfig.mockReturnValue({
|
||||
gateway: { mode: "local", bind: "lan" },
|
||||
});
|
||||
@@ -293,7 +297,10 @@ describe("buildGatewayConnectionDetails", () => {
|
||||
pickPrimaryTailnetIPv4.mockReturnValue(undefined);
|
||||
pickPrimaryLanIPv4.mockReturnValue("10.0.0.5");
|
||||
|
||||
expect(() => buildGatewayConnectionDetails()).toThrow("SECURITY ERROR");
|
||||
const details = buildGatewayConnectionDetails();
|
||||
|
||||
expect(details.url).toBe("ws://127.0.0.1:18800");
|
||||
expect(details.urlSource).toBe("local loopback");
|
||||
});
|
||||
|
||||
it("prefers remote url when configured", () => {
|
||||
|
||||
Reference in New Issue
Block a user