From e43600c9e5fc469f0e65d4e38e73973c5b0fed37 Mon Sep 17 00:00:00 2001 From: Tyler Yust Date: Thu, 26 Mar 2026 04:54:57 -0700 Subject: [PATCH] fix(bluebubbles): auto-allow private network for local serverUrl and add allowPrivateNetwork to channel schema --- extensions/bluebubbles/src/account-resolve.ts | 13 ++++++++++++- src/config/zod-schema.providers-core.ts | 1 + 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/extensions/bluebubbles/src/account-resolve.ts b/extensions/bluebubbles/src/account-resolve.ts index f4ac1f06618..226c09c298d 100644 --- a/extensions/bluebubbles/src/account-resolve.ts +++ b/extensions/bluebubbles/src/account-resolve.ts @@ -1,6 +1,8 @@ +import { isBlockedHostnameOrIp } from "openclaw/plugin-sdk/infra-runtime"; import { resolveBlueBubblesAccount } from "./accounts.js"; import type { OpenClawConfig } from "./runtime-api.js"; import { normalizeResolvedSecretInputString } from "./secret-input.js"; +import { normalizeBlueBubblesServerUrl } from "./types.js"; export type BlueBubblesAccountResolveOpts = { serverUrl?: string; @@ -43,10 +45,19 @@ export function resolveBlueBubblesServerAccount(params: BlueBubblesAccountResolv if (!password) { throw new Error("BlueBubbles password is required"); } + + let autoAllowPrivateNetwork = false; + try { + const hostname = new URL(normalizeBlueBubblesServerUrl(baseUrl)).hostname.trim(); + autoAllowPrivateNetwork = Boolean(hostname) && isBlockedHostnameOrIp(hostname); + } catch { + autoAllowPrivateNetwork = false; + } + return { baseUrl, password, accountId: account.accountId, - allowPrivateNetwork: account.config.allowPrivateNetwork === true, + allowPrivateNetwork: account.config.allowPrivateNetwork === true || autoAllowPrivateNetwork, }; } diff --git a/src/config/zod-schema.providers-core.ts b/src/config/zod-schema.providers-core.ts index 108062b9bdf..ce4d5a4156f 100644 --- a/src/config/zod-schema.providers-core.ts +++ b/src/config/zod-schema.providers-core.ts @@ -1409,6 +1409,7 @@ export const BlueBubblesAccountSchemaBase = z mediaMaxMb: z.number().int().positive().optional(), mediaLocalRoots: z.array(z.string()).optional(), sendReadReceipts: z.boolean().optional(), + allowPrivateNetwork: z.boolean().optional(), blockStreaming: z.boolean().optional(), blockStreamingCoalesce: BlockStreamingCoalesceSchema.optional(), groups: z.record(z.string(), BlueBubblesGroupConfigSchema.optional()).optional(),