fix(telegram): hide tool progress by default#71351
Conversation
🔒 Aisle Security AnalysisWe found 1 potential security issue(s) in this PR:
1. 🟡 Telegram preview Markdown injection via capped inline-code backtick fence in tool-progress formatting
Description
Because Telegram preview rendering later calls This enables:
Vulnerable code: const maxBacktickRun = Math.max(
0,
...Array.from(clipped.matchAll(/`+/g), (match) => match[0].length),
);
const fence = "`".repeat(Math.min(maxBacktickRun + 1, MAX_PROGRESS_MARKDOWN_FENCE_CHARS));
return `${fence}${clipped}${fence}`;Example payload (in tool progress text) that can break out when
This would generate a 10-backtick fence, which is not longer than the internal 10-backtick run, allowing the injected RecommendationDo not cap the fence length below Safer options:
const fence = "`".repeat(maxBacktickRun + 1);
return `${fence}${clipped}${fence}`;
import { escapeHtml } from "./format"; // or a local helper
function formatProgressAsHtmlCode(text: string): string {
const clipped = clipProgressMarkdownText(text);
return `<code>${escapeHtml(clipped)}</code>`;
}…and ensure preview updates use
const sanitized = clipped.replace(/`/g, "ˋ");
return `\`${sanitized}\``;Any approach should guarantee that attacker-controlled content cannot terminate the intended code span and introduce new Telegram entities (links/mentions). Analyzed PR: #71351 at commit Last updated on: 2026-04-25T02:27:29Z |
Greptile SummaryThis PR changes Telegram's tool-progress behavior from opt-out to opt-in by passing Confidence Score: 5/5Safe to merge — the change is Telegram-scoped, well-tested, and does not affect other channels or delivery paths. No logical, security, or correctness issues found. The default override is correctly threaded through the function call, suppressDefaultToolProgressMessages is correctly made unconditional, tests cover both the off (default) and on (opt-in) paths, and all documentation is aligned. No files require special attention. Reviews (1): Last reviewed commit: "fix(telegram): hide tool progress by def..." | Re-trigger Greptile |
|
Addressed the review findings in follow-up commit 2edd0dd4fd. What changed:
Why the behavior is still safe:
Validation:
Known unrelated validation note:
|
|
@codex /review |
2edd0dd to
529f89a
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2edd0dd4fd
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| const fence = "`".repeat(maxBacktickRun + 1); | ||
| return `${fence}${text}${fence}`; |
There was a problem hiding this comment.
Handle edge backticks when wrapping progress text in code spans
The new wrapper builds ${fence}${text}${fence} directly, which breaks for progress strings that start or end with a backtick because the delimiter run merges with content (for example, input `foo becomes `````foo````). In that case markdown no longer treats it as code, so link/format parsing can reappear in Telegram previews despite this change intending to neutralize it. This affects Telegram when streaming.preview.toolProgress=true and a tool/item progress line begins or ends with `.
Useful? React with 👍 / 👎.
529f89a to
ee6927a
Compare
|
Deep-reviewed and pushed a maintainer fixup on top of this PR. Review findings:
What I changed:
Local verification:
Thanks @neeravmakwana. |
|
Landed via rebase onto main.
Thanks @neeravmakwana. |
Summary
Root Cause
Telegram enabled
resolveChannelStreamingPreviewToolProgress()with the shared default oftrue, so tool/item/plan lifecycle events were turned into visibleWorking…preview text during normal Telegram replies. Disabling that path alone would have allowed the genericWorking:progress messages to surface separately, so Telegram also needs to suppress default tool-progress message delivery at runtime.Why This Is Safe
The change is Telegram-scoped. Final assistant replies, block streaming, reasoning streaming, status reactions, media tool payloads, approval payloads, and error delivery continue to use the existing delivery paths. Users who intentionally want visible Telegram progress can still opt in with
channels.telegram.streaming.preview.toolProgress=true, which keeps progress inside the edited preview message.Security / Runtime Controls Unchanged
This does not rely on prompt instructions. The suppression is enforced in the Telegram dispatch runtime via
suppressDefaultToolProgressMessages, while the existing runtime filtering that still allows media, approval, and error payloads remains unchanged.Self-Review
Tests
pnpm test extensions/telegram/src/bot-message-dispatch.test.ts(pass)pnpm test:extension telegram(pass)pnpm config:docs:check(pass)git diff --check(pass)pnpm check:changed(fails in unrelated extension-wide typecheck before reaching changed tests; errors are duplicate nested@mariozechner/pi-ai/pi-agent-coretype identities in other extensions such asextensions/amazon-bedrock-mantle,extensions/anthropic, andextensions/codex)Made with Cursor