fix: preserve Telegram topic routing for exec completions#64580
Conversation
Greptile SummaryThis PR pins the originating Confidence Score: 5/5Safe to merge — targeted fix with direct regression test coverage for the topic-drift scenario. All findings are P2 style suggestions (one redundant normalizeDeliveryContext call). The core fix — pinning DeliveryContext on ProcessSession at spawn time — is correct, and three new tests exercise the exact failure mode from production. No files require special attention. Prompt To Fix All With AIThis is a comment left during a code review.
Path: src/agents/bash-tools.exec-runtime.ts
Line: 577
Comment:
**Double `normalizeDeliveryContext` call**
`opts.notifyDeliveryContext` has already been normalized in `bash-tools.exec.ts` via `normalizeDeliveryContext({...})` before being passed in here (lines 1326–1331 in `bash-tools.exec.ts`). Calling `normalizeDeliveryContext` again on the session is redundant, though harmless. You could store it directly:
```suggestion
notifyDeliveryContext: opts.notifyDeliveryContext,
```
How can I resolve this? If you propose a fix, please make it concise.Reviews (1): Last reviewed commit: "clawdbot-a2c: pin exec completion delive..." | Re-trigger Greptile |
| @@ -564,6 +574,7 @@ export async function runExecProcess(opts: { | |||
| command: opts.command, | |||
| scopeKey: opts.scopeKey, | |||
| sessionKey: opts.sessionKey, | |||
| notifyDeliveryContext: normalizeDeliveryContext(opts.notifyDeliveryContext), | |||
There was a problem hiding this comment.
Double
normalizeDeliveryContext call
opts.notifyDeliveryContext has already been normalized in bash-tools.exec.ts via normalizeDeliveryContext({...}) before being passed in here (lines 1326–1331 in bash-tools.exec.ts). Calling normalizeDeliveryContext again on the session is redundant, though harmless. You could store it directly:
| notifyDeliveryContext: normalizeDeliveryContext(opts.notifyDeliveryContext), | |
| notifyDeliveryContext: opts.notifyDeliveryContext, |
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/agents/bash-tools.exec-runtime.ts
Line: 577
Comment:
**Double `normalizeDeliveryContext` call**
`opts.notifyDeliveryContext` has already been normalized in `bash-tools.exec.ts` via `normalizeDeliveryContext({...})` before being passed in here (lines 1326–1331 in `bash-tools.exec.ts`). Calling `normalizeDeliveryContext` again on the session is redundant, though harmless. You could store it directly:
```suggestion
notifyDeliveryContext: opts.notifyDeliveryContext,
```
How can I resolve this? If you propose a fix, please make it concise.
🔒 Aisle Security AnalysisWe found 1 potential security issue(s) in this PR:
1. 🟡 Ambiguous/unvalidated DeliveryContext fields allow delimiter/control-character injection into deliveryContextKey
Description
This becomes security-relevant because delivery-context keys are used to group/compare routing contexts (e.g., announce queues, session delivery comparisons). If an attacker can influence
Vulnerable code: const to = normalizeOptionalString(context.to);
...
return `${normalized.channel}|${normalized.to}|${normalized.accountId ?? ""}|${threadId}`;Although this diff primarily adds new call sites that pass RecommendationHarden
Example (reject unsafe characters and ensure threadId is consistently stringified): const UNSAFE_RE = /[\r\n\u0000-\u001f\u007f|]/;
function normalizeSafeField(v: unknown): string | undefined {
const s = normalizeOptionalString(v);
if (!s) return undefined;
if (UNSAFE_RE.test(s)) return undefined; // or escape
return s;
}
export function normalizeDeliveryContext(context?: DeliveryContext): DeliveryContext | undefined {
if (!context) return undefined;
const channel = normalizeSafeField(context.channel);
const to = normalizeSafeField(context.to);
const accountId = normalizeAccountId(context.accountId);
const threadIdRaw = (typeof context.threadId === "number" && Number.isFinite(context.threadId))
? String(Math.trunc(context.threadId))
: normalizeSafeField(context.threadId);
if (!channel && !to && !accountId && !threadIdRaw) return undefined;
return { channel, to, accountId, ...(threadIdRaw ? { threadId: threadIdRaw } : {}) };
}
export function deliveryContextKey(context?: DeliveryContext): string | undefined {
const n = normalizeDeliveryContext(context);
if (!n?.channel || !n?.to) return undefined;
return JSON.stringify([n.channel, n.to, n.accountId ?? "", n.threadId ?? ""]);
}Also ensure downstream routing code uses the normalized/validated form exclusively. Analyzed PR: #64580 at commit Last updated on: 2026-04-11T22:35:42Z |
b896d96 to
d2a4b38
Compare
Regeneration-Prompt: | Fix a Telegram forum topic misroute where delayed exec completion or similar async completion text could be delivered into the wrong topic after the session's stored route drifted. Keep the patch surgical. Preserve immutable origin deliveryContext when background exec completion events are queued, thread that context from the exec tool's ambient channel/session defaults into the process session, and ensure the queued system event carries it instead of relying on later heartbeat fallback to mutable session lastTo/lastThreadId data. Add one focused unit assertion that notifyOnExit events keep the original Telegram topic delivery context and one heartbeat regression that proves work started in topic 47 still delivers back to topic 47 even if the session store later points at topic 2175.
Regeneration-Prompt: | Prepare PR openclaw#64580 after review-pr with no blocking findings. The only required prep change was the workflow-mandated changelog entry under CHANGELOG.md -> Unreleased -> Fixes. Preserve the review conclusion that the code change is already acceptable, do not widen scope beyond the changelog, and include the PR number plus thanks attribution in the changelog line for the Telegram exec forum-topic completion routing fix.
d2a4b38 to
f13fb58
Compare
…4580) * clawdbot-a2c: pin exec completion delivery context Regeneration-Prompt: | Fix a Telegram forum topic misroute where delayed exec completion or similar async completion text could be delivered into the wrong topic after the session's stored route drifted. Keep the patch surgical. Preserve immutable origin deliveryContext when background exec completion events are queued, thread that context from the exec tool's ambient channel/session defaults into the process session, and ensure the queued system event carries it instead of relying on later heartbeat fallback to mutable session lastTo/lastThreadId data. Add one focused unit assertion that notifyOnExit events keep the original Telegram topic delivery context and one heartbeat regression that proves work started in topic 47 still delivers back to topic 47 even if the session store later points at topic 2175. * fix: note Telegram exec topic routing Regeneration-Prompt: | Prepare PR openclaw#64580 after review-pr with no blocking findings. The only required prep change was the workflow-mandated changelog entry under CHANGELOG.md -> Unreleased -> Fixes. Preserve the review conclusion that the code change is already acceptable, do not widen scope beyond the changelog, and include the PR number plus thanks attribution in the changelog line for the Telegram exec forum-topic completion routing fix.
…4580) * clawdbot-a2c: pin exec completion delivery context Regeneration-Prompt: | Fix a Telegram forum topic misroute where delayed exec completion or similar async completion text could be delivered into the wrong topic after the session's stored route drifted. Keep the patch surgical. Preserve immutable origin deliveryContext when background exec completion events are queued, thread that context from the exec tool's ambient channel/session defaults into the process session, and ensure the queued system event carries it instead of relying on later heartbeat fallback to mutable session lastTo/lastThreadId data. Add one focused unit assertion that notifyOnExit events keep the original Telegram topic delivery context and one heartbeat regression that proves work started in topic 47 still delivers back to topic 47 even if the session store later points at topic 2175. * fix: note Telegram exec topic routing Regeneration-Prompt: | Prepare PR openclaw#64580 after review-pr with no blocking findings. The only required prep change was the workflow-mandated changelog entry under CHANGELOG.md -> Unreleased -> Fixes. Preserve the review conclusion that the code change is already acceptable, do not widen scope beyond the changelog, and include the PR number plus thanks attribution in the changelog line for the Telegram exec forum-topic completion routing fix.
…4580) * clawdbot-a2c: pin exec completion delivery context Regeneration-Prompt: | Fix a Telegram forum topic misroute where delayed exec completion or similar async completion text could be delivered into the wrong topic after the session's stored route drifted. Keep the patch surgical. Preserve immutable origin deliveryContext when background exec completion events are queued, thread that context from the exec tool's ambient channel/session defaults into the process session, and ensure the queued system event carries it instead of relying on later heartbeat fallback to mutable session lastTo/lastThreadId data. Add one focused unit assertion that notifyOnExit events keep the original Telegram topic delivery context and one heartbeat regression that proves work started in topic 47 still delivers back to topic 47 even if the session store later points at topic 2175. * fix: note Telegram exec topic routing Regeneration-Prompt: | Prepare PR openclaw#64580 after review-pr with no blocking findings. The only required prep change was the workflow-mandated changelog entry under CHANGELOG.md -> Unreleased -> Fixes. Preserve the review conclusion that the code change is already acceptable, do not widen scope beyond the changelog, and include the PR number plus thanks attribution in the changelog line for the Telegram exec forum-topic completion routing fix.
…4580) * clawdbot-a2c: pin exec completion delivery context Regeneration-Prompt: | Fix a Telegram forum topic misroute where delayed exec completion or similar async completion text could be delivered into the wrong topic after the session's stored route drifted. Keep the patch surgical. Preserve immutable origin deliveryContext when background exec completion events are queued, thread that context from the exec tool's ambient channel/session defaults into the process session, and ensure the queued system event carries it instead of relying on later heartbeat fallback to mutable session lastTo/lastThreadId data. Add one focused unit assertion that notifyOnExit events keep the original Telegram topic delivery context and one heartbeat regression that proves work started in topic 47 still delivers back to topic 47 even if the session store later points at topic 2175. * fix: note Telegram exec topic routing Regeneration-Prompt: | Prepare PR openclaw#64580 after review-pr with no blocking findings. The only required prep change was the workflow-mandated changelog entry under CHANGELOG.md -> Unreleased -> Fixes. Preserve the review conclusion that the code change is already acceptable, do not widen scope beyond the changelog, and include the PR number plus thanks attribution in the changelog line for the Telegram exec forum-topic completion routing fix.
…4580) * clawdbot-a2c: pin exec completion delivery context Regeneration-Prompt: | Fix a Telegram forum topic misroute where delayed exec completion or similar async completion text could be delivered into the wrong topic after the session's stored route drifted. Keep the patch surgical. Preserve immutable origin deliveryContext when background exec completion events are queued, thread that context from the exec tool's ambient channel/session defaults into the process session, and ensure the queued system event carries it instead of relying on later heartbeat fallback to mutable session lastTo/lastThreadId data. Add one focused unit assertion that notifyOnExit events keep the original Telegram topic delivery context and one heartbeat regression that proves work started in topic 47 still delivers back to topic 47 even if the session store later points at topic 2175. * fix: note Telegram exec topic routing Regeneration-Prompt: | Prepare PR openclaw#64580 after review-pr with no blocking findings. The only required prep change was the workflow-mandated changelog entry under CHANGELOG.md -> Unreleased -> Fixes. Preserve the review conclusion that the code change is already acceptable, do not widen scope beyond the changelog, and include the PR number plus thanks attribution in the changelog line for the Telegram exec forum-topic completion routing fix.
…4580) * clawdbot-a2c: pin exec completion delivery context Regeneration-Prompt: | Fix a Telegram forum topic misroute where delayed exec completion or similar async completion text could be delivered into the wrong topic after the session's stored route drifted. Keep the patch surgical. Preserve immutable origin deliveryContext when background exec completion events are queued, thread that context from the exec tool's ambient channel/session defaults into the process session, and ensure the queued system event carries it instead of relying on later heartbeat fallback to mutable session lastTo/lastThreadId data. Add one focused unit assertion that notifyOnExit events keep the original Telegram topic delivery context and one heartbeat regression that proves work started in topic 47 still delivers back to topic 47 even if the session store later points at topic 2175. * fix: note Telegram exec topic routing Regeneration-Prompt: | Prepare PR openclaw#64580 after review-pr with no blocking findings. The only required prep change was the workflow-mandated changelog entry under CHANGELOG.md -> Unreleased -> Fixes. Preserve the review conclusion that the code change is already acceptable, do not widen scope beyond the changelog, and include the PR number plus thanks attribution in the changelog line for the Telegram exec forum-topic completion routing fix.
…4580) * clawdbot-a2c: pin exec completion delivery context Regeneration-Prompt: | Fix a Telegram forum topic misroute where delayed exec completion or similar async completion text could be delivered into the wrong topic after the session's stored route drifted. Keep the patch surgical. Preserve immutable origin deliveryContext when background exec completion events are queued, thread that context from the exec tool's ambient channel/session defaults into the process session, and ensure the queued system event carries it instead of relying on later heartbeat fallback to mutable session lastTo/lastThreadId data. Add one focused unit assertion that notifyOnExit events keep the original Telegram topic delivery context and one heartbeat regression that proves work started in topic 47 still delivers back to topic 47 even if the session store later points at topic 2175. * fix: note Telegram exec topic routing Regeneration-Prompt: | Prepare PR openclaw#64580 after review-pr with no blocking findings. The only required prep change was the workflow-mandated changelog entry under CHANGELOG.md -> Unreleased -> Fixes. Preserve the review conclusion that the code change is already acceptable, do not widen scope beyond the changelog, and include the PR number plus thanks attribution in the changelog line for the Telegram exec forum-topic completion routing fix.
What
Preserves the originating delivery context for delayed exec completion events so Telegram forum-topic completions stay pinned to the topic where the work started, even if the session's stored route later drifts to a different topic.
Why
Background exec completions were being queued by session key alone and later re-resolved from mutable session routing state. In Telegram forum topics that could redirect a completion started in one topic into another topic.
Changes
Testing
pnpm test src/agents/bash-tools.exec-runtime.test.ts src/agents/bash-tools.test.ts src/infra/heartbeat-runner.ghost-reminder.test.ts