mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-12 07:20:45 +00:00
fix(browser): add IP validation, fix upgrade handler for non-loopback bind
- Zod schema: validate relayBindHost with ipv4/ipv6 instead of bare string - Upgrade handler: allow non-loopback connections when bindHost is explicitly non-loopback (e.g. 0.0.0.0 for WSL2), keeping loopback-only default - Test: verify actual bind address via relay.bindHost instead of just checking reachability on 127.0.0.1 which passes regardless - Expose bindHost on ChromeExtensionRelayServer type for inspection Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
committed by
Peter Steinberger
parent
436ae8a07c
commit
e883d0b556
@@ -1179,8 +1179,9 @@ describe("chrome extension relay server", () => {
|
||||
bindHost: "0.0.0.0",
|
||||
});
|
||||
expect(relay.port).toBe(port);
|
||||
// Verify the server actually bound to 0.0.0.0, not the cdpUrl host.
|
||||
expect(relay.bindHost).toBe("0.0.0.0");
|
||||
|
||||
// Relay should be reachable on loopback (0.0.0.0 accepts all interfaces).
|
||||
const res = await fetch(`http://127.0.0.1:${port}/`);
|
||||
expect(res.status).toBe(200);
|
||||
},
|
||||
@@ -1194,6 +1195,7 @@ describe("chrome extension relay server", () => {
|
||||
cdpUrl = `http://127.0.0.1:${port}`;
|
||||
const relay = await ensureChromeExtensionRelayServer({ cdpUrl });
|
||||
expect(relay.host).toBe("127.0.0.1");
|
||||
expect(relay.bindHost).toBe("127.0.0.1");
|
||||
|
||||
const res = await fetch(`http://127.0.0.1:${port}/`);
|
||||
expect(res.status).toBe(200);
|
||||
|
||||
@@ -113,6 +113,7 @@ function getRelayAuthTokenFromRequest(req: IncomingMessage, url?: URL): string |
|
||||
|
||||
export type ChromeExtensionRelayServer = {
|
||||
host: string;
|
||||
bindHost: string;
|
||||
port: number;
|
||||
baseUrl: string;
|
||||
cdpWsUrl: string;
|
||||
@@ -684,7 +685,9 @@ export async function ensureChromeExtensionRelayServer(opts: {
|
||||
const pathname = url.pathname;
|
||||
const remote = req.socket.remoteAddress;
|
||||
|
||||
if (!isLoopbackAddress(remote)) {
|
||||
// When bindHost is explicitly non-loopback (e.g. 0.0.0.0 for WSL2),
|
||||
// allow non-loopback connections; otherwise enforce loopback-only.
|
||||
if (!isLoopbackAddress(remote) && isLoopbackHost(bindHost)) {
|
||||
rejectUpgrade(socket, 403, "Forbidden");
|
||||
return;
|
||||
}
|
||||
@@ -978,6 +981,7 @@ export async function ensureChromeExtensionRelayServer(opts: {
|
||||
) {
|
||||
const existingRelay: ChromeExtensionRelayServer = {
|
||||
host: info.host,
|
||||
bindHost,
|
||||
port: info.port,
|
||||
baseUrl: info.baseUrl,
|
||||
cdpWsUrl: `ws://${info.host}:${info.port}/cdp`,
|
||||
@@ -999,6 +1003,7 @@ export async function ensureChromeExtensionRelayServer(opts: {
|
||||
|
||||
const relay: ChromeExtensionRelayServer = {
|
||||
host,
|
||||
bindHost,
|
||||
port,
|
||||
baseUrl,
|
||||
cdpWsUrl: `ws://${host}:${port}/cdp`,
|
||||
|
||||
@@ -372,7 +372,7 @@ export const OpenClawSchema = z
|
||||
)
|
||||
.optional(),
|
||||
extraArgs: z.array(z.string()).optional(),
|
||||
relayBindHost: z.string().optional(),
|
||||
relayBindHost: z.union([z.string().ipv4(), z.string().ipv6()]).optional(),
|
||||
})
|
||||
.strict()
|
||||
.optional(),
|
||||
|
||||
Reference in New Issue
Block a user