openclaw - ✅(Solved) Fix BlueBubbles: SSRF allowlist doesn't cover reactions (react action blocked on private IP) [2 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#59722Fetched 2026-04-08 02:41:23
View on GitHub
Comments
0
Participants
1
Timeline
0
Reactions
0

The BlueBubbles channel's auto-allowlist for the configured serverUrl doesn't cover the react action. Reactions to messages fail with:

Blocked hostname or private/internal/special-use IP address

Root Cause

The BlueBubbles channel's auto-allowlist for the configured serverUrl doesn't cover the react action. Reactions to messages fail with:

Blocked hostname or private/internal/special-use IP address

Fix Action

Workaround

None found. There's no documented config to allowlist private IPs for channel plugin API calls.

PR fix notes

PR #67510: fix(bluebubbles): restore inbound image attachments and accept updated-message events

Description (problem / solution / changelog)

Summary

Four interconnected fixes for BlueBubbles inbound media that together restore image attachment handling on Node 22+:

  1. Strip bundled-undici dispatcher from non-SSRF fetch pathblueBubblesFetchWithTimeout's non-SSRF fallback was spreading a bundled-undici dispatcher into globalThis.fetch(), which Node 22's built-in undici rejects with TypeError: invalid onRequestStart method. This silently broke ALL inbound attachment downloads. (#64105, #61861, #67241, #62530)

  2. Accept updated-message events carrying attachments — BlueBubbles fires updated-message when attachments are indexed after the initial new-message (which may arrive with attachments: []). The webhook handler was filtering these out as non-reaction events. (#65430)

  3. Event-type-aware dedup key — the persistent GUID dedup now suffixes updated-message keys with :updated so follow-up attachment events aren't rejected as duplicates of the already-committed new-message. (Relates to #52277)

  4. Retry attachment fetch for empty arrays — when the initial webhook arrives with empty attachments (image-only messages or updated-message events), waits 2s and re-fetches from the BB API as a fallback. (Relates to #67437)

Test plan

  • pnpm tsgo — no new type errors
  • pnpm test extensions/bluebubbles/ — 434 tests pass (9 new tests added)
  • Manual: send standalone image via iMessage → agent receives and processes it
  • Manual: send text + image together → agent receives both
  • pnpm build — verify no [INEFFECTIVE_DYNAMIC_IMPORT] warnings

Issues closed

Closes #64105, closes #61861, closes #65430, closes #67241, closes #62530.

Related issues (not fixed by this PR)

  • #34749 — image attachments blocked by SSRF guard (localhost URL) — partially addressed by the dispatcher fix, but the broader SSRF allowlist for localhost BB servers is a separate concern
  • #57181 — SSRF guard blocks BB plugin internal API calls to private IP — same broader SSRF allowlist issue
  • #59722 — SSRF allowlist doesn't cover reactions — separate SSRF scope gap
  • #60715 — BB health check fails on LAN/private serverUrl — separate SSRF/health-check issue

Superseded PRs

  • #66120 — accept updated-message events carrying attachments (fully subsumed by fix #2)
  • #67437 — retry attachment fetch when webhook arrives with empty array (fully subsumed by fix #4)
  • #66108 — route fetchImpl through bundled undici fetch on Node 24+ (different approach to same dispatcher issue, subsumed by fix #1)

Related PRs

  • #52277 — dedupe webhook replays without dropping edits (assigned to @omarshahine, complementary finer-grained edit dedup)

🤖 Generated with Claude Code

Changed files

  • CHANGELOG.md (modified, +1/-0)
  • extensions/bluebubbles/src/attachments.test.ts (modified, +88/-1)
  • extensions/bluebubbles/src/attachments.ts (modified, +52/-2)
  • extensions/bluebubbles/src/inbound-dedupe.test.ts (modified, +36/-0)
  • extensions/bluebubbles/src/inbound-dedupe.ts (modified, +15/-3)
  • extensions/bluebubbles/src/monitor-normalize.ts (modified, +5/-1)
  • extensions/bluebubbles/src/monitor-processing.ts (modified, +50/-6)
  • extensions/bluebubbles/src/monitor.ts (modified, +13/-3)
  • extensions/bluebubbles/src/types.ts (modified, +9/-1)
  • scripts/check-no-raw-channel-fetch.mjs (modified, +1/-1)

PR #68234: bluebubbles: consolidate HTTP traffic through typed BlueBubblesClient

Description (problem / solution / changelog)

Draft — not yet ready for merge. Opening for early review feedback; will also smoke-test on Lobster before marking ready.

Summary

All outbound BlueBubbles HTTP calls now route through a single typed BlueBubblesClient that resolves SSRF policy and auth material once at construction. Previously each of the 17 callsites computed its own SsrFPolicy and threaded it through blueBubblesFetchWithTimeout — the per-callsite divergence is what caused #34749 (image attachments blocked on localhost) and #59722 (reactions blocked on private IPs).

What closes

  • Closes #34749 — image attachments blocked by SSRF guard (localhost). downloadAttachment now threads this.ssrfPolicy to BOTH fetchRemoteMedia AND the fetchImpl callback, where the legacy helper silently omitted the policy on the callback path.
  • Closes #59722 — reactions not covered by allowlist. reactions.ts now uses the same policy as every other call; the asymmetric {} fallback that blocked private-IP BB deployments is gone.

How

New extensions/bluebubbles/src/client.ts:

  • BlueBubblesClient class with typed operations (request, requestJson, requestMultipart, ping, getServerInfo, react, getMessageAttachments, downloadAttachment).
  • createBlueBubblesClient({cfg, accountId, serverUrl, password, ...}) for full-config callers.
  • createBlueBubblesClientFromParts({baseUrl, password, allowPrivateNetwork, ...}) for low-level helpers that already have the resolved tuple.
  • Three-mode SSRF policy resolved once at construction (previously inlined in attachments.ts only):
    1. { allowPrivateNetwork: true } — user opted in
    2. { allowedHostnames: [trustedHost] } — narrow allowlist
    3. undefined — non-SSRF fallback path
  • Pluggable BlueBubblesAuthStrategy with blueBubblesQueryStringAuth (default, preserves current ?password=) and blueBubblesHeaderAuth so the #66869 header-auth cutover becomes a one-line default flip.

Migrated: attachments.ts, reactions.ts, probe.ts, chat.ts, send.ts, history.ts, catchup.ts, monitor-processing.ts all now route through the client. Public function signatures preserved for compatibility.

Test fixtures: monitor.test.ts and monitor.webhook-auth.test.ts install the shared SSRF-guard passthrough (createBlueBubblesFetchGuardPassthroughInstaller) — required because the consolidation moves callers from the unguarded fallback onto the mode-2 allowlist for self-hosted BB servers.

Size

+171 / -310 LOC across BB files (139-line net reduction). 28 new tests in client.test.ts, full BB suite stays at 462/462.

Verification

  • pnpm test extensions/bluebubbles — 22 files / 462 tests pass
  • pnpm lint extensions/bluebubbles/src/ — 0 warnings / 0 errors (82 files)
  • pnpm tsgo — pre-existing unrelated errors on origin/main (codex/discord/qa-lab/src/commands); none in bluebubbles
  • pnpm build — pre-existing amazon-bedrock-mantle runtime-deps staging error on clean main; unrelated
  • Smoke test on Lobster before marking ready for review

Deferred to follow-ups (intentionally NOT in this PR)

  • #66869 header auth cutoverAuthStrategy interface is in place; flipping the default requires BB Server coordination.
  • #67752 SSRF tightening — centralized policy resolution makes this a single-point-of-change follow-up.
  • Delete blueBubblesFetchWithTimeout / buildBlueBubblesApiUrl from types.ts — they're now private-to-client infrastructure; safe to remove once this lands.

Blocks #57181, #60715 (both become instance-level tests against BlueBubblesClient once this lands).

🤖 Generated with Claude Code

Changed files

  • extensions/bluebubbles/src/attachments.test.ts (modified, +5/-1)
  • extensions/bluebubbles/src/attachments.ts (modified, +32/-117)
  • extensions/bluebubbles/src/catchup.ts (modified, +17/-22)
  • extensions/bluebubbles/src/chat.ts (modified, +19/-49)
  • extensions/bluebubbles/src/client.test.ts (added, +613/-0)
  • extensions/bluebubbles/src/client.ts (added, +570/-0)
  • extensions/bluebubbles/src/history.ts (modified, +12/-9)
  • extensions/bluebubbles/src/monitor-processing.ts (modified, +13/-20)
  • extensions/bluebubbles/src/monitor.test.ts (modified, +11/-0)
  • extensions/bluebubbles/src/monitor.webhook-auth.test.ts (modified, +7/-0)
  • extensions/bluebubbles/src/multipart.ts (modified, +17/-3)
  • extensions/bluebubbles/src/probe.ts (modified, +15/-17)
  • extensions/bluebubbles/src/reactions.ts (modified, +9/-26)
  • extensions/bluebubbles/src/send.ts (modified, +33/-50)

Code Example

Blocked hostname or private/internal/special-use IP address
RAW_BUFFERClick to expand / collapse

Summary

The BlueBubbles channel's auto-allowlist for the configured serverUrl doesn't cover the react action. Reactions to messages fail with:

Blocked hostname or private/internal/special-use IP address

Environment

  • OpenClaw version: 2026.4.1
  • BlueBubbles serverUrl: http://192.168.x.x:1234 (private IP)
  • macOS

Steps to reproduce

  1. Configure BlueBubbles with a private IP serverUrl
  2. Receive a message via BlueBubbles webhook (works fine)
  3. Send a reply via message action=send (works fine)
  4. Try to react via message action=reactblocked by SSRF

Expected behavior

The SSRF auto-allowlist fix from #27648 should cover all BlueBubbles API calls, not just attachment fetches.

Relevant changelog entry

BlueBubbles/SSRF: auto-allowlist the configured serverUrl hostname for attachment fetches so localhost/private-IP BlueBubbles setups are no longer false-blocked by default SSRF checks.

This fix appears to only apply to attachment fetches, leaving reactions (and possibly other actions like edit/unsend) blocked.

Workaround

None found. There's no documented config to allowlist private IPs for channel plugin API calls.

extent analysis

TL;DR

The BlueBubbles channel's auto-allowlist for private IP server URLs may need to be extended to cover the react action to prevent SSRF blocking.

Guidance

  • Review the SSRF auto-allowlist configuration to determine if it can be manually extended to include the react action.
  • Investigate if there are any undocumented configuration options or environment variables that can be used to allowlist private IPs for channel plugin API calls.
  • Consider modifying the BlueBubbles server URL to use a public IP or a hostname that is not blocked by SSRF checks.
  • Verify if the issue is specific to the react action or if other actions like edit or unsend are also affected.

Example

No code snippet is provided as the issue does not imply a specific code change.

Notes

The provided changelog entry suggests that the SSRF auto-allowlist fix only applies to attachment fetches, which may indicate a limitation in the current implementation. The issue may require a modification to the auto-allowlist configuration or the BlueBubbles server setup.

Recommendation

Apply a workaround by modifying the BlueBubbles server URL to use a public IP or a hostname that is not blocked by SSRF checks, as there is no clear indication of a fixed version that addresses this issue.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

The SSRF auto-allowlist fix from #27648 should cover all BlueBubbles API calls, not just attachment fetches.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix BlueBubbles: SSRF allowlist doesn't cover reactions (react action blocked on private IP) [2 pull requests, 1 participants]