@openclaw/bluebubbles 2026.2.9 → 2026.2.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/monitor.test.ts +40 -28
- package/src/monitor.ts +0 -4
package/package.json
CHANGED
package/src/monitor.test.ts
CHANGED
|
@@ -254,9 +254,20 @@ function createMockRequest(
|
|
|
254
254
|
body: unknown,
|
|
255
255
|
headers: Record<string, string> = {},
|
|
256
256
|
): IncomingMessage {
|
|
257
|
+
const parsedUrl = new URL(url, "http://localhost");
|
|
258
|
+
const hasAuthQuery = parsedUrl.searchParams.has("guid") || parsedUrl.searchParams.has("password");
|
|
259
|
+
const hasAuthHeader =
|
|
260
|
+
headers["x-guid"] !== undefined ||
|
|
261
|
+
headers["x-password"] !== undefined ||
|
|
262
|
+
headers["x-bluebubbles-guid"] !== undefined ||
|
|
263
|
+
headers.authorization !== undefined;
|
|
264
|
+
if (!hasAuthQuery && !hasAuthHeader) {
|
|
265
|
+
parsedUrl.searchParams.set("password", "test-password");
|
|
266
|
+
}
|
|
267
|
+
|
|
257
268
|
const req = new EventEmitter() as IncomingMessage;
|
|
258
269
|
req.method = method;
|
|
259
|
-
req.url =
|
|
270
|
+
req.url = `${parsedUrl.pathname}${parsedUrl.search}`;
|
|
260
271
|
req.headers = headers;
|
|
261
272
|
(req as unknown as { socket: { remoteAddress: string } }).socket = { remoteAddress: "127.0.0.1" };
|
|
262
273
|
|
|
@@ -546,40 +557,41 @@ describe("BlueBubbles webhook monitor", () => {
|
|
|
546
557
|
expect(res.statusCode).toBe(401);
|
|
547
558
|
});
|
|
548
559
|
|
|
549
|
-
it("
|
|
560
|
+
it("requires authentication for loopback requests when password is configured", async () => {
|
|
550
561
|
const account = createMockAccount({ password: "secret-token" });
|
|
551
562
|
const config: OpenClawConfig = {};
|
|
552
563
|
const core = createMockRuntime();
|
|
553
564
|
setBlueBubblesRuntime(core);
|
|
565
|
+
for (const remoteAddress of ["127.0.0.1", "::1", "::ffff:127.0.0.1"]) {
|
|
566
|
+
const req = createMockRequest("POST", "/bluebubbles-webhook", {
|
|
567
|
+
type: "new-message",
|
|
568
|
+
data: {
|
|
569
|
+
text: "hello",
|
|
570
|
+
handle: { address: "+15551234567" },
|
|
571
|
+
isGroup: false,
|
|
572
|
+
isFromMe: false,
|
|
573
|
+
guid: "msg-1",
|
|
574
|
+
},
|
|
575
|
+
});
|
|
576
|
+
(req as unknown as { socket: { remoteAddress: string } }).socket = {
|
|
577
|
+
remoteAddress,
|
|
578
|
+
};
|
|
554
579
|
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
guid: "msg-1",
|
|
563
|
-
},
|
|
564
|
-
});
|
|
565
|
-
// Localhost address
|
|
566
|
-
(req as unknown as { socket: { remoteAddress: string } }).socket = {
|
|
567
|
-
remoteAddress: "127.0.0.1",
|
|
568
|
-
};
|
|
569
|
-
|
|
570
|
-
unregister = registerBlueBubblesWebhookTarget({
|
|
571
|
-
account,
|
|
572
|
-
config,
|
|
573
|
-
runtime: { log: vi.fn(), error: vi.fn() },
|
|
574
|
-
core,
|
|
575
|
-
path: "/bluebubbles-webhook",
|
|
576
|
-
});
|
|
580
|
+
const loopbackUnregister = registerBlueBubblesWebhookTarget({
|
|
581
|
+
account,
|
|
582
|
+
config,
|
|
583
|
+
runtime: { log: vi.fn(), error: vi.fn() },
|
|
584
|
+
core,
|
|
585
|
+
path: "/bluebubbles-webhook",
|
|
586
|
+
});
|
|
577
587
|
|
|
578
|
-
|
|
579
|
-
|
|
588
|
+
const res = createMockResponse();
|
|
589
|
+
const handled = await handleBlueBubblesWebhookRequest(req, res);
|
|
590
|
+
expect(handled).toBe(true);
|
|
591
|
+
expect(res.statusCode).toBe(401);
|
|
580
592
|
|
|
581
|
-
|
|
582
|
-
|
|
593
|
+
loopbackUnregister();
|
|
594
|
+
}
|
|
583
595
|
});
|
|
584
596
|
|
|
585
597
|
it("ignores unregistered webhook paths", async () => {
|
package/src/monitor.ts
CHANGED
|
@@ -1533,10 +1533,6 @@ export async function handleBlueBubblesWebhookRequest(
|
|
|
1533
1533
|
if (guid && guid.trim() === token) {
|
|
1534
1534
|
return true;
|
|
1535
1535
|
}
|
|
1536
|
-
const remote = req.socket?.remoteAddress ?? "";
|
|
1537
|
-
if (remote === "127.0.0.1" || remote === "::1" || remote === "::ffff:127.0.0.1") {
|
|
1538
|
-
return true;
|
|
1539
|
-
}
|
|
1540
1536
|
return false;
|
|
1541
1537
|
});
|
|
1542
1538
|
|