fix(security): prevent cross-channel reply routing in shared sessions#24571
Merged
steipete merged 3 commits intoopenclaw:mainfrom Feb 25, 2026
Merged
Conversation
arosstale
approved these changes
Feb 23, 2026
Contributor
arosstale
left a comment
There was a problem hiding this comment.
Clean fix for a real privacy bug. The turn-source channel override pattern is the right approach — it pins reply routing to the originating channel rather than trusting the mutable session-level lastChannel. The null-coalescing fallbacks (turnSourceTo ?? context?.to) preserve backward compatibility when the caller doesn't set the new fields. Tests cover the cross-channel race. LGTM.
steipete
added a commit
that referenced
this pull request
Feb 25, 2026
Contributor
|
Landed via temp rebase onto main.
Thanks @brandonwise! |
steipete
added a commit
that referenced
this pull request
Feb 25, 2026
steipete
added a commit
that referenced
this pull request
Feb 25, 2026
joshavant
pushed a commit
that referenced
this pull request
Feb 25, 2026
margulans
pushed a commit
to margulans/Neiron-AI-assistant
that referenced
this pull request
Feb 25, 2026
Jackson3195
pushed a commit
to Jackson3195/openclaw-with-a-personal-touch
that referenced
this pull request
Feb 25, 2026
brianleach
pushed a commit
to brianleach/openclaw
that referenced
this pull request
Feb 26, 2026
2 tasks
execute008
pushed a commit
to execute008/openclaw
that referenced
this pull request
Feb 27, 2026
r4jiv007
pushed a commit
to r4jiv007/openclaw
that referenced
this pull request
Feb 28, 2026
6 tasks
hughdidit
pushed a commit
to hughdidit/DAISy-Agency
that referenced
this pull request
Mar 1, 2026
…@brandonwise) (cherry picked from commit 885452f) # Conflicts: # src/infra/outbound/agent-delivery.ts # src/infra/outbound/targets.test.ts # src/infra/outbound/targets.ts
hughdidit
pushed a commit
to hughdidit/DAISy-Agency
that referenced
this pull request
Mar 3, 2026
…@brandonwise) (cherry picked from commit 885452f) # Conflicts: # src/infra/outbound/agent-delivery.ts # src/infra/outbound/targets.test.ts # src/infra/outbound/targets.ts
GixGosu
pushed a commit
to GixGosu/openclaw
that referenced
this pull request
Mar 3, 2026
…rce routing This fixes group message routing failures introduced in v2026.2.24 when PR openclaw#24571 added fail-closed security hardening for shared-session cross-channel replies. The issue: `buildEmbeddedContextFromTemplate` was only setting `messageProvider` but not `messageChannel`. The delivery planner's `turnSourceChannel` logic reads from `runContext.messageChannel`, so without it set, the turn-source binding fails and replies to group messages don't route back to the originating channel. This affects all plugin-based channels (Mattermost, etc.) and potentially built-in channels (Telegram, WhatsApp) in group/channel contexts where the session might be shared across channels. The fix adds `messageChannel` alongside `messageProvider` using the same resolved value from `resolveOriginMessageProvider`. Related issues: - openclaw#24571 (original security hardening PR) - openclaw#29637 (Telegram group messages not working) - openclaw#19509 (WhatsApp group messages not working) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
GixGosu
pushed a commit
to GixGosu/openclaw
that referenced
this pull request
Mar 3, 2026
…tibility The change in v2026.2.24 that made pairing store DM-only broke existing setups where users relied on DM pairing to access group chats. This restores the previous behavior where storeAllowFrom is included in effectiveGroupAllowFrom. Note: Command authorization in groups still requires explicit allowlist (not pairing store) to maintain security separation. See: openclaw#24571 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
GixGosu
pushed a commit
to GixGosu/openclaw
that referenced
this pull request
Mar 3, 2026
…tibility The change in v2026.2.24 that made pairing store DM-only broke existing setups where users relied on DM pairing to access group chats. This restores the previous behavior where storeAllowFrom is included in effectiveGroupAllowFrom. Added groupAuthIncludesPairingStore option (defaults to true) for users who want to opt into the stricter v2026.2.24 behavior. Note: Command authorization in groups still requires explicit allowlist (not pairing store) to maintain security separation. See: openclaw#24571 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
GixGosu
pushed a commit
to GixGosu/openclaw
that referenced
this pull request
Mar 3, 2026
…rce routing This fixes group message routing failures introduced in v2026.2.24 when PR openclaw#24571 added fail-closed security hardening for shared-session cross-channel replies. The issue: `buildEmbeddedContextFromTemplate` was only setting `messageProvider` but not `messageChannel`. The delivery planner's `turnSourceChannel` logic reads from `runContext.messageChannel`, so without it set, the turn-source binding fails and replies to group messages don't route back to the originating channel. This affects all plugin-based channels (Mattermost, etc.) and potentially built-in channels (Telegram, WhatsApp) in group/channel contexts where the session might be shared across channels. The fix adds `messageChannel` alongside `messageProvider` using the same resolved value from `resolveOriginMessageProvider`. Related issues: - openclaw#24571 (original security hardening PR) - openclaw#29637 (Telegram group messages not working) - openclaw#19509 (WhatsApp group messages not working) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
GixGosu
pushed a commit
to GixGosu/openclaw
that referenced
this pull request
Mar 3, 2026
…tibility The change in v2026.2.24 that made pairing store DM-only broke existing setups where users relied on DM pairing to access group chats. This restores the previous behavior where storeAllowFrom is included in effectiveGroupAllowFrom. Added groupAuthIncludesPairingStore option (defaults to true) for users who want to opt into the stricter v2026.2.24 behavior. Note: Command authorization in groups still requires explicit allowlist (not pairing store) to maintain security separation. See: openclaw#24571 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
GixGosu
pushed a commit
to GixGosu/openclaw
that referenced
this pull request
Mar 3, 2026
…rce routing This fixes group message routing failures introduced in v2026.2.24 when PR openclaw#24571 added fail-closed security hardening for shared-session cross-channel replies. The issue: `buildEmbeddedContextFromTemplate` was only setting `messageProvider` but not `messageChannel`. The delivery planner's `turnSourceChannel` logic reads from `runContext.messageChannel`, so without it set, the turn-source binding fails and replies to group messages don't route back to the originating channel. This affects all plugin-based channels (Mattermost, etc.) and potentially built-in channels (Telegram, WhatsApp) in group/channel contexts where the session might be shared across channels. The fix adds `messageChannel` alongside `messageProvider` using the same resolved value from `resolveOriginMessageProvider`. Related issues: - openclaw#24571 (original security hardening PR) - openclaw#29637 (Telegram group messages not working) - openclaw#19509 (WhatsApp group messages not working) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
GixGosu
pushed a commit
to GixGosu/openclaw
that referenced
this pull request
Mar 3, 2026
…tibility The change in v2026.2.24 that made pairing store DM-only broke existing setups where users relied on DM pairing to access group chats. This restores the previous behavior where storeAllowFrom is included in effectiveGroupAllowFrom. Added groupAuthIncludesPairingStore option (defaults to true) for users who want to opt into the stricter v2026.2.24 behavior. Note: Command authorization in groups still requires explicit allowlist (not pairing store) to maintain security separation. See: openclaw#24571 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
GixGosu
pushed a commit
to GixGosu/openclaw
that referenced
this pull request
Mar 3, 2026
…rce routing This fixes group message routing failures introduced in v2026.2.24 when PR openclaw#24571 added fail-closed security hardening for shared-session cross-channel replies. The issue: `buildEmbeddedContextFromTemplate` was only setting `messageProvider` but not `messageChannel`. The delivery planner's `turnSourceChannel` logic reads from `runContext.messageChannel`, so without it set, the turn-source binding fails and replies to group messages don't route back to the originating channel. This affects all plugin-based channels (Mattermost, etc.) and potentially built-in channels (Telegram, WhatsApp) in group/channel contexts where the session might be shared across channels. The fix adds `messageChannel` alongside `messageProvider` using the same resolved value from `resolveOriginMessageProvider`. Related issues: - openclaw#24571 (original security hardening PR) - openclaw#29637 (Telegram group messages not working) - openclaw#19509 (WhatsApp group messages not working) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
GixGosu
pushed a commit
to GixGosu/openclaw
that referenced
this pull request
Mar 3, 2026
…tibility The change in v2026.2.24 that made pairing store DM-only broke existing setups where users relied on DM pairing to access group chats. This restores the previous behavior where storeAllowFrom is included in effectiveGroupAllowFrom. Added groupAuthIncludesPairingStore option (defaults to true) for users who want to opt into the stricter v2026.2.24 behavior. Note: Command authorization in groups still requires explicit allowlist (not pairing store) to maintain security separation. See: openclaw#24571 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
GixGosu
pushed a commit
to GixGosu/openclaw
that referenced
this pull request
Mar 3, 2026
…rce routing This fixes group message routing failures introduced in v2026.2.24 when PR openclaw#24571 added fail-closed security hardening for shared-session cross-channel replies. The issue: `buildEmbeddedContextFromTemplate` was only setting `messageProvider` but not `messageChannel`. The delivery planner's `turnSourceChannel` logic reads from `runContext.messageChannel`, so without it set, the turn-source binding fails and replies to group messages don't route back to the originating channel. This affects all plugin-based channels (Mattermost, etc.) and potentially built-in channels (Telegram, WhatsApp) in group/channel contexts where the session might be shared across channels. The fix adds `messageChannel` alongside `messageProvider` using the same resolved value from `resolveOriginMessageProvider`. Related issues: - openclaw#24571 (original security hardening PR) - openclaw#29637 (Telegram group messages not working) - openclaw#19509 (WhatsApp group messages not working) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
GixGosu
pushed a commit
to GixGosu/openclaw
that referenced
this pull request
Mar 3, 2026
…tibility The change in v2026.2.24 that made pairing store DM-only broke existing setups where users relied on DM pairing to access group chats. This restores the previous behavior where storeAllowFrom is included in effectiveGroupAllowFrom. Added groupAuthIncludesPairingStore option (defaults to true) for users who want to opt into the stricter v2026.2.24 behavior. Note: Command authorization in groups still requires explicit allowlist (not pairing store) to maintain security separation. See: openclaw#24571 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
GixGosu
pushed a commit
to GixGosu/openclaw
that referenced
this pull request
Mar 3, 2026
…rce routing This fixes group message routing failures introduced in v2026.2.24 when PR openclaw#24571 added fail-closed security hardening for shared-session cross-channel replies. The issue: `buildEmbeddedContextFromTemplate` was only setting `messageProvider` but not `messageChannel`. The delivery planner's `turnSourceChannel` logic reads from `runContext.messageChannel`, so without it set, the turn-source binding fails and replies to group messages don't route back to the originating channel. This affects all plugin-based channels (Mattermost, etc.) and potentially built-in channels (Telegram, WhatsApp) in group/channel contexts where the session might be shared across channels. The fix adds `messageChannel` alongside `messageProvider` using the same resolved value from `resolveOriginMessageProvider`. Related issues: - openclaw#24571 (original security hardening PR) - openclaw#29637 (Telegram group messages not working) - openclaw#19509 (WhatsApp group messages not working) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
GixGosu
pushed a commit
to GixGosu/openclaw
that referenced
this pull request
Mar 3, 2026
…tibility The change in v2026.2.24 that made pairing store DM-only broke existing setups where users relied on DM pairing to access group chats. This restores the previous behavior where storeAllowFrom is included in effectiveGroupAllowFrom. Added groupAuthIncludesPairingStore option (defaults to true) for users who want to opt into the stricter v2026.2.24 behavior. Note: Command authorization in groups still requires explicit allowlist (not pairing store) to maintain security separation. See: openclaw#24571 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
18 tasks
GixGosu
pushed a commit
to GixGosu/openclaw
that referenced
this pull request
Mar 4, 2026
…rce routing This fixes group message routing failures introduced in v2026.2.24 when PR openclaw#24571 added fail-closed security hardening for shared-session cross-channel replies. The issue: `buildEmbeddedContextFromTemplate` was only setting `messageProvider` but not `messageChannel`. The delivery planner's `turnSourceChannel` logic reads from `runContext.messageChannel`, so without it set, the turn-source binding fails and replies to group messages don't route back to the originating channel. This affects all plugin-based channels (Mattermost, etc.) and potentially built-in channels (Telegram, WhatsApp) in group/channel contexts where the session might be shared across channels. The fix adds `messageChannel` alongside `messageProvider` using the same resolved value from `resolveOriginMessageProvider`. Related issues: - openclaw#24571 (original security hardening PR) - openclaw#29637 (Telegram group messages not working) - openclaw#19509 (WhatsApp group messages not working) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
GixGosu
pushed a commit
to GixGosu/openclaw
that referenced
this pull request
Mar 4, 2026
…tibility The change in v2026.2.24 that made pairing store DM-only broke existing setups where users relied on DM pairing to access group chats. This restores the previous behavior where storeAllowFrom is included in effectiveGroupAllowFrom. Added groupAuthIncludesPairingStore option (defaults to true) for users who want to opt into the stricter v2026.2.24 behavior. Note: Command authorization in groups still requires explicit allowlist (not pairing store) to maintain security separation. See: openclaw#24571 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
zooqueen
pushed a commit
to hanzoai/bot
that referenced
this pull request
Mar 6, 2026
thebenjaminlee
pushed a commit
to escape-velocity-ventures/openclaw
that referenced
this pull request
Mar 7, 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
Fixes #24152 — cross-channel reply routing privacy leak in shared sessions.
Problem
When
dmScope="main"(the default), all DM channels share a single session. The session'slastChannel/lastTofields get overwritten by each inbound message, regardless of source channel.Race condition: If a Slack DM arrives while the agent is generating a WhatsApp reply,
lastChannelflips to"slack"and the reply routes to the Slack sender instead of the WhatsApp user — a privacy violation.Reproduction conditions (from issue):
Fix
Adds optional
turnSourceChannel,turnSourceTo,turnSourceAccountId, andturnSourceThreadIdparameters to:resolveSessionDeliveryTarget()intargets.tsresolveAgentDeliveryPlan()inagent-delivery.tsWhen
turnSourceChannelis set, it overrides the session-levellastChannelfor"last"channel resolution. This ensures the reply always routes back to the channel that originated the turn, regardless of concurrent inbound messages from other channels.Key design decisions:
requestedChannel/explicitToparameter styleChanges
src/infra/outbound/targets.tsturnSource*params toresolveSessionDeliveryTarget()src/infra/outbound/agent-delivery.tsturnSource*params toresolveAgentDeliveryPlan(), pass through to target resolutionsrc/infra/outbound/targets.test.tsTest cases
turnSourceChanneloverrides sessionlastChannelwhen providedlastChannelwhenturnSourceChannelis absentrequestedChanneltakes priority overturnSourceChannelturnSourceAccountIdandturnSourceThreadIdNext steps
Upstream callers (channel monitors, agent turn pipeline) need to pass
turnSourceChannelwhen initiating turns. This PR provides the infrastructure; wiring the callers is a follow-up.AI-assisted: Claude analyzed the routing code and authored the fix. Human reviewed the approach and design decisions.
Greptile Summary
Adds optional
turnSource*parameters to delivery resolution functions to prevent cross-channel reply routing in shared sessions (dmScope="main"). When a turn originates from WhatsApp but a concurrent Slack message updates the session'slastChannel, replies could be misrouted to Slack—this fix ensures replies route back to the originating channel by letting callers override session state with turn-specific context.Key changes:
resolveSessionDeliveryTarget()andresolveAgentDeliveryPlan()accept new optionalturnSourceChannel,turnSourceTo,turnSourceAccountId, andturnSourceThreadIdparametersturnSourceChannelis set, it overrides session-levellastChannelfor"last"channel resolutionAs noted in PR description: This provides the infrastructure; upstream callers (channel monitors, agent turn pipeline) need updates in follow-up work to pass turn source context.
Confidence Score: 5/5
Last reviewed commit: 53250c8