diff --git a/.changeset/fix-ipv6-session-broker-origins.md b/.changeset/fix-ipv6-session-broker-origins.md new file mode 100644 index 000000000..231df1adf --- /dev/null +++ b/.changeset/fix-ipv6-session-broker-origins.md @@ -0,0 +1,5 @@ +--- +"hunkdiff": patch +--- + +Fix session commands when the local daemon uses the IPv6 loopback address. diff --git a/src/session-broker/brokerConfig.test.ts b/src/session-broker/brokerConfig.test.ts index 0e22fcad0..e782f75f1 100644 --- a/src/session-broker/brokerConfig.test.ts +++ b/src/session-broker/brokerConfig.test.ts @@ -24,6 +24,20 @@ describe("Hunk session daemon config", () => { ).toMatchObject({ host: "localhost", port: 49000 }); }); + test("formats IPv6 literal origins with URL authority brackets", () => { + expect( + resolveSessionBrokerConfig({ + [SESSION_BROKER_HOST_ENV]: "::1", + [SESSION_BROKER_PORT_ENV]: "49000", + }), + ).toMatchObject({ + host: "::1", + port: 49000, + httpOrigin: "http://[::1]:49000", + wsOrigin: "ws://[::1]:49000", + }); + }); + test("accepts loopback hosts without an unsafe override", () => { expect(isLoopbackHost("127.0.0.1")).toBe(true); expect(isLoopbackHost("127.1.2.3")).toBe(true); diff --git a/src/session-broker/brokerConfig.ts b/src/session-broker/brokerConfig.ts index 504390860..9753745b3 100644 --- a/src/session-broker/brokerConfig.ts +++ b/src/session-broker/brokerConfig.ts @@ -63,10 +63,13 @@ export function resolveSessionBrokerConfig( ); } + // URL authorities require brackets around literal IPv6 addresses, unlike socket APIs. + const urlHost = isIP(host) === 6 ? `[${host}]` : host; + return { host, port, - httpOrigin: `http://${host}:${port}`, - wsOrigin: `ws://${host}:${port}`, + httpOrigin: `http://${urlHost}:${port}`, + wsOrigin: `ws://${urlHost}:${port}`, }; }