Skip to content

Commit 8a9e23f

Browse files
committed
fix(whatsapp): validate WebSocket URL env
1 parent 0deddfa commit 8a9e23f

2 files changed

Lines changed: 37 additions & 3 deletions

File tree

extensions/whatsapp/src/session.test.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,25 @@ describe("web session", () => {
449449
expect(readLastSocketOptions().waWebSocketUrl).toBeUndefined();
450450
});
451451

452+
it("rejects invalid OPENCLAW_WHATSAPP_WEB_SOCKET_URL values", async () => {
453+
vi.stubEnv(OPENCLAW_WHATSAPP_WEB_SOCKET_URL_ENV, "http://127.0.0.1:14567/ws");
454+
455+
await expect(createWaSocket(false, false)).rejects.toThrow(
456+
"OPENCLAW_WHATSAPP_WEB_SOCKET_URL must use ws:// or wss://.",
457+
);
458+
expect(baileys.makeWASocket).not.toHaveBeenCalled();
459+
});
460+
461+
it("preserves explicit Baileys WebSocket URL options over invalid environment", async () => {
462+
vi.stubEnv(OPENCLAW_WHATSAPP_WEB_SOCKET_URL_ENV, "http://127.0.0.1:49153/ws/chat");
463+
464+
await createWaSocket(false, false, {
465+
waWebSocketUrl: "ws://127.0.0.1:49154/ws/chat",
466+
});
467+
468+
expect(readLastSocketOptions().waWebSocketUrl).toBe("ws://127.0.0.1:49154/ws/chat");
469+
});
470+
452471
it("uses ambient env proxy agent when HTTPS_PROXY is configured", async () => {
453472
vi.stubEnv("HTTPS_PROXY", "http://proxy.test:8080");
454473

extensions/whatsapp/src/session.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,23 @@ function resolveWaWebSocketUrl(value: string | URL | undefined): string | URL |
133133
return value.trim() || undefined;
134134
}
135135

136+
function resolveEnvWaWebSocketUrl(): string | undefined {
137+
const value = resolveWaWebSocketUrl(process.env[OPENCLAW_WHATSAPP_WEB_SOCKET_URL_ENV]);
138+
if (!value) {
139+
return undefined;
140+
}
141+
let url: URL;
142+
try {
143+
url = new URL(value);
144+
} catch {
145+
throw new Error(`${OPENCLAW_WHATSAPP_WEB_SOCKET_URL_ENV} must be a valid URL.`);
146+
}
147+
if (url.protocol !== "ws:" && url.protocol !== "wss:") {
148+
throw new Error(`${OPENCLAW_WHATSAPP_WEB_SOCKET_URL_ENV} must use ws:// or wss://.`);
149+
}
150+
return url.toString();
151+
}
152+
136153
/**
137154
* Create a Baileys socket backed by the multi-file auth store we keep on disk.
138155
* Consumers can opt into QR printing for interactive login flows.
@@ -172,6 +189,7 @@ export async function createWaSocket(
172189
await writeCredsJsonAtomically(authDir, state.creds);
173190
};
174191
const { version } = await fetchLatestBaileysVersion();
192+
const waWebSocketUrl = resolveWaWebSocketUrl(opts.waWebSocketUrl) ?? resolveEnvWaWebSocketUrl();
175193
const agent = await resolveEnvProxyAgent(sessionLogger);
176194
const fetchAgent = await resolveEnvFetchDispatcher(sessionLogger, agent);
177195
const socketTiming = {
@@ -181,9 +199,6 @@ export async function createWaSocket(
181199
defaultQueryTimeoutMs:
182200
opts.defaultQueryTimeoutMs ?? DEFAULT_WHATSAPP_SOCKET_TIMING.defaultQueryTimeoutMs,
183201
};
184-
const waWebSocketUrl =
185-
resolveWaWebSocketUrl(opts.waWebSocketUrl) ??
186-
resolveWaWebSocketUrl(process.env[OPENCLAW_WHATSAPP_WEB_SOCKET_URL_ENV]);
187202
const sock = makeWASocket({
188203
auth: {
189204
creds: state.creds,

0 commit comments

Comments
 (0)