VYPR
High severity7.3NVD Advisory· Published May 11, 2026· Updated May 16, 2026

CVE-2026-8305

CVE-2026-8305

Description

A vulnerability was detected in OpenClaw up to 2026.1.24. The impacted element is the function handleBlueBubblesWebhookRequest of the file extensions/bluebubbles/src/monitor.ts of the component bluebubbles Webhook. Performing a manipulation results in improper authentication. It is possible to initiate the attack remotely. The exploit is now public and may be used. Upgrading to version 2026.2.12 is sufficient to resolve this issue. The patch is named a6653be0265f1f02b9de46c06f52ea7c81a836e6. The affected component should be upgraded.

Affected products

1

Patches

2
a6653be0265f

fix(an-08): apply security fix

https://github.com/openclaw/openclawCoy GeekFeb 11, 2026via nvd-ref
2 files changed · +2 7
  • extensions/bluebubbles/src/monitor.test.ts+2 3 modified
    @@ -238,7 +238,6 @@ function createMockAccount(
         configured: true,
         config: {
           serverUrl: "http://localhost:1234",
    -      password: "test-password",
           dmPolicy: "open",
           groupPolicy: "open",
           allowFrom: [],
    @@ -546,7 +545,7 @@ describe("BlueBubbles webhook monitor", () => {
           expect(res.statusCode).toBe(401);
         });
     
    -    it("allows localhost requests without authentication", async () => {
    +    it("requires authentication for localhost requests when password is configured", async () => {
           const account = createMockAccount({ password: "secret-token" });
           const config: OpenClawConfig = {};
           const core = createMockRuntime();
    @@ -579,7 +578,7 @@ describe("BlueBubbles webhook monitor", () => {
           const handled = await handleBlueBubblesWebhookRequest(req, res);
     
           expect(handled).toBe(true);
    -      expect(res.statusCode).toBe(200);
    +      expect(res.statusCode).toBe(401);
         });
     
         it("ignores unregistered webhook paths", async () => {
    
  • extensions/bluebubbles/src/monitor.ts+0 4 modified
    @@ -1533,10 +1533,6 @@ export async function handleBlueBubblesWebhookRequest(
         if (guid && guid.trim() === token) {
           return true;
         }
    -    const remote = req.socket?.remoteAddress ?? "";
    -    if (remote === "127.0.0.1" || remote === "::1" || remote === "::ffff:127.0.0.1") {
    -      return true;
    -    }
         return false;
       });
     
    
f836c385ffc7

fix: BlueBubbles webhook auth bypass via loopback proxy trust (#13787)

https://github.com/openclaw/openclawCoy GeekFeb 12, 2026via nvd-ref
2 files changed · +40 32
  • extensions/bluebubbles/src/monitor.test.ts+40 28 modified
    @@ -254,9 +254,20 @@ function createMockRequest(
       body: unknown,
       headers: Record<string, string> = {},
     ): IncomingMessage {
    +  const parsedUrl = new URL(url, "http://localhost");
    +  const hasAuthQuery = parsedUrl.searchParams.has("guid") || parsedUrl.searchParams.has("password");
    +  const hasAuthHeader =
    +    headers["x-guid"] !== undefined ||
    +    headers["x-password"] !== undefined ||
    +    headers["x-bluebubbles-guid"] !== undefined ||
    +    headers.authorization !== undefined;
    +  if (!hasAuthQuery && !hasAuthHeader) {
    +    parsedUrl.searchParams.set("password", "test-password");
    +  }
    +
       const req = new EventEmitter() as IncomingMessage;
       req.method = method;
    -  req.url = url;
    +  req.url = `${parsedUrl.pathname}${parsedUrl.search}`;
       req.headers = headers;
       (req as unknown as { socket: { remoteAddress: string } }).socket = { remoteAddress: "127.0.0.1" };
     
    @@ -546,40 +557,41 @@ describe("BlueBubbles webhook monitor", () => {
           expect(res.statusCode).toBe(401);
         });
     
    -    it("allows localhost requests without authentication", async () => {
    +    it("requires authentication for loopback requests when password is configured", async () => {
           const account = createMockAccount({ password: "secret-token" });
           const config: OpenClawConfig = {};
           const core = createMockRuntime();
           setBlueBubblesRuntime(core);
    +      for (const remoteAddress of ["127.0.0.1", "::1", "::ffff:127.0.0.1"]) {
    +        const req = createMockRequest("POST", "/bluebubbles-webhook", {
    +          type: "new-message",
    +          data: {
    +            text: "hello",
    +            handle: { address: "+15551234567" },
    +            isGroup: false,
    +            isFromMe: false,
    +            guid: "msg-1",
    +          },
    +        });
    +        (req as unknown as { socket: { remoteAddress: string } }).socket = {
    +          remoteAddress,
    +        };
     
    -      const req = createMockRequest("POST", "/bluebubbles-webhook", {
    -        type: "new-message",
    -        data: {
    -          text: "hello",
    -          handle: { address: "+15551234567" },
    -          isGroup: false,
    -          isFromMe: false,
    -          guid: "msg-1",
    -        },
    -      });
    -      // Localhost address
    -      (req as unknown as { socket: { remoteAddress: string } }).socket = {
    -        remoteAddress: "127.0.0.1",
    -      };
    -
    -      unregister = registerBlueBubblesWebhookTarget({
    -        account,
    -        config,
    -        runtime: { log: vi.fn(), error: vi.fn() },
    -        core,
    -        path: "/bluebubbles-webhook",
    -      });
    +        const loopbackUnregister = registerBlueBubblesWebhookTarget({
    +          account,
    +          config,
    +          runtime: { log: vi.fn(), error: vi.fn() },
    +          core,
    +          path: "/bluebubbles-webhook",
    +        });
     
    -      const res = createMockResponse();
    -      const handled = await handleBlueBubblesWebhookRequest(req, res);
    +        const res = createMockResponse();
    +        const handled = await handleBlueBubblesWebhookRequest(req, res);
    +        expect(handled).toBe(true);
    +        expect(res.statusCode).toBe(401);
     
    -      expect(handled).toBe(true);
    -      expect(res.statusCode).toBe(200);
    +        loopbackUnregister();
    +      }
         });
     
         it("ignores unregistered webhook paths", async () => {
    
  • extensions/bluebubbles/src/monitor.ts+0 4 modified
    @@ -1533,10 +1533,6 @@ export async function handleBlueBubblesWebhookRequest(
         if (guid && guid.trim() === token) {
           return true;
         }
    -    const remote = req.socket?.remoteAddress ?? "";
    -    if (remote === "127.0.0.1" || remote === "::1" || remote === "::ffff:127.0.0.1") {
    -      return true;
    -    }
         return false;
       });
     
    

Vulnerability mechanics

AI mechanics synthesis has not run for this CVE yet.

References

8

News mentions

15