fix(qqbot): Batch-2 salvage — SSRF allowlist, voice preflight, group auth, WS reconnect wait - #11567
Merged
Merged
Conversation
When a WebSocket-based platform adapter (e.g. QQ Bot) temporarily loses its connection, send() now polls is_connected for up to 15s instead of immediately returning a non-retryable failure. If the auto-reconnect completes within the window, the message is delivered normally. On timeout, the SendResult is marked retryable=True so the base class retry mechanism can attempt re-delivery. Same treatment applied to _send_media(). Adds 4 async tests covering: - Successful send after simulated reconnection - Retryable failure on timeout - Immediate success when already connected - _send_media reconnection wait Fixes #11163
This was referenced Apr 17, 2026
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.
Summary
Batch-2 QQBot salvage — four independent contributor fixes landed together, each with preserved per-commit authorship. Will rebase-merge to keep individual attribution.
Included PRs
◆ #11388 @yeyitech —
fix: allow trusted QQ CDN benchmark IP resolutionCurrent main's
tools/url_safety.pyhas no hostname allowlist, so when a local proxy remaps QQ's CDN (multimedia.nt.qq.com.cn) into benchmark IP space (198.18.0.0/15), SSRF protection blocks all QQ image/voice downloads. PR adds a narrow allowlist: exact hostname match + HTTPS required. Tests cover subdomain rejection, HTTP rejection, DNS-failure rejection.Closes #11284.
◆ #11294 @plgonzalezrx8 —
Fix QQ voice attachment SSRF validation_stt_voice_attachment()ingateway/platforms/qqbot.pydownloaded attacker-supplied URLs with no SSRF check._download_and_cache()was already guarded — this brings STT in line. Also attaches the shared_ssrf_redirect_guardevent hook to the httpx client so redirect chains are validated too.◆ #10316 @dieutx —
fix(gateway): honor QQ_GROUP_ALLOWED_USERS in runner authRoot cause:
_is_user_authorized()mappedPlatform.QQBOT → QQ_ALLOWED_USERSonly, checked againstsource.user_id. QQ group allowlisting is keyed bysource.chat_id(group openid), soQQ_GROUP_ALLOWED_USERSwas never consulted — group messages that passedQQAdapter._is_group_allowed()got rejected at runner auth. PR adds aplatform_group_env_map, checkschat_type == "group", authorizes by chat_id. Includes AUTHOR_MAP entry.◆ #11164 @LehaoLin —
fix(gateway): wait for reconnection before dropping WebSocket sendsWhen QQBot's WebSocket briefly disconnects,
send()and_send_media()previously returned immediately with a non-retryable failure — messages silently dropped during the ~1s reconnect window. PR adds_wait_for_reconnection()polling (15s cap, 500ms interval) and marks timeout failures asretryable=Trueso base_send_with_retrycan handle it.Closes #11163.
Verification
origin/main(eabe14a)py_compileOK on all 7 touched filestest_url_safety,test_qqbot,test_unauthorized_dm_behavior,test_weixin,test_platform_base,test_send_image_fileAUTHOR_MAP additions
dangtc94@gmail.com → dieutx(from @dieutx's own commit in fix(gateway): honor QQ_GROUP_ALLOWED_USERS in runner auth #10316)lehaolin98@outlook.com → LehaoLin(mine)yeyitech,plgonzalezrx8auto-resolve via noreply patternNot included in this batch
#10257 (@Quon — qqbot media upload in send_message tool): flagged for separate review. The PR has a no-op
passin the media-only guard that falls through to the error return instead of skipping it, and the follow-up commit583757cbbundles a platform-guard regression alongside the msg_id fix. The Authorization header typo (QQBotAccessToken→QQBot) IS a real live bug and will be landed as a minimal follow-up after this batch.On merge
Will close #11388, #11294, #10316, #11164 with credit pointing to this PR.