fix(gateway): reject empty BlueBubbles webhook token + refuse unauthenticated non-loopback bind - #36862
Closed
dhyabi2 wants to merge 1 commit into
Closed
fix(gateway): reject empty BlueBubbles webhook token + refuse unauthenticated non-loopback bind#36862dhyabi2 wants to merge 1 commit into
dhyabi2 wants to merge 1 commit into
Conversation
…henticated non-loopback bind The webhook auth built the token from an or-chain over five request-supplied sources and compared it with 'token != self.password'. self.password defaults to '' when BLUEBUBBLES_PASSWORD is unset, and supplying any source as an empty value makes the chain return '', so '' == '' authenticated the request. Reject empty tokens, use hmac.compare_digest for constant-time comparison, and refuse to start when bound to a non-loopback host without a password (mirrors the api_server.py guard). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Author
|
Withdrawing this — on closer analysis the reported bypass is not reachable.
# gateway/platforms/bluebubbles.py:160-165
async def connect(self) -> bool:
if not self.server_url or not self.password:
logger.error("[bluebubbles] BLUEBUBBLES_SERVER_URL and BLUEBUBBLES_PASSWORD are required")
return FalseThe webhook is bound only inside (The other three reports — #36846, #36847, #36848 — are unaffected and remain reproducible.) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
The BlueBubbles webhook builds its auth token from an
or-chain over five request-supplied sources and compares it withtoken != self.password.self.passworddefaults to""whenBLUEBUBBLES_PASSWORDis unset, and supplying any source as an empty value makes the chain return"", so"" != ""isFalse→ the request authenticates. When the adapter is network-exposed without a password, an attacker can forge inbound iMessage webhook events.Reproduction (empty-valued header bypasses auth when no password is set):
The fix
hmac.compare_digestfor constant-time comparison: require bothtokenandself.passwordto be non-empty.0.0.0.0) without a password set — mirroring the existing guard ingateway/platforms/api_server.py.How to test
Default
127.0.0.1bind without a password still starts (loopback only); a0.0.0.0bind without a password now raises at startup instead of exposing an open webhook.Platforms
Logic-only change in
gateway/platforms/bluebubbles.py.Fixes #36849. Reported privately as part of
GHSA-gmqw-rqrf-c48w(closed 2026-05-14 without a fix); still reproducible onmain.