Repository navigation
Conversation
…eliver Telegram parses every message with parse_mode HTML, but issue titles, errors, URLs and trigger reasons went in raw. A title such as "Vec<u8> & co" made Telegram reject the message as malformed HTML, and a crafted title could inject markup into the chat. None of the message templates carry markup of their own, so the text is escaped once at the send boundary instead of per interpolated value: no future interpolation can forget it. Truncation to Telegram's 4096 character limit now happens on the plain text before escaping, since the limit counts parsed characters and cutting after escaping could split an entity. Also removes the file's section-header comments. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
🟢 Tier S · Ready to merge
Adds shared HTML escaping for Telegram message text and applies it at the send boundary after plain-text truncation. Adds unit and request-body regression tests for markup characters, errors, and truncation.
📂 Walkthrough · 3
Reviewed |
This branch has not been deployed
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.
Stacked on #171; depends on #161 (Docker toolchain).
What changed
TelegramNotifier::send_message_with_idsescapes&,<,>and"in the message text before posting it withparse_mode: "HTML". Everynotify_*andask_questiongoes through this one path, so issue titles, sources, errors, PR URLs, trigger reasons, completion reasons and questions are all escaped.notifier/html.rs(html::escape), next to the notifiers that render HTML....marker as named constants.// --- ... ---section-header comments are removed.Why
Telegram parses these messages as HTML, but every value was interpolated raw. A title like
Vec<u8> & comakes Telegram reject the message as malformed HTML (so the notification is lost), and a crafted title or error could inject markup into the chat.None of the message templates contain markup of their own, so the whole text is escaped once at the send boundary instead of per interpolated value. That way a future interpolation can't skip the escape. Escaping after truncation means the cut can never split an entity such as
&, and Telegram counts its limit on the parsed text.How it was verified
claudear-verify.sh /Users/jakebarnby/Local/claudear/.claude/worktrees/migrate-clb clb ready: passed (fmt, clippy-D warnings, workspace tests).MockTelegramClient:test_notify_start_escapes_html_in_title: a title of<script>alert(1)</script> & "co"is posted as<script>alert(1)</script> & "co".test_notify_failed_escapes_html_in_error: an error containingVec<u8>and&is escaped.test_send_message_truncates_before_escaping: 5000&characters come out as exactly 4082 whole&entities followed by..., with no split entity.claudear-verify.sh … clb scoped - -- -p claudear-integrations --lib notifier::telegramgave 121 passed and 3 failed, and the failures showed the raw<script>,&andVec<u8>text in the posted body.html.rshas unit tests for markup characters, re-escaping existing entities, and unchanged plain text.What was NOT verified
Behaviour differences
&,<,>or"now shows in Telegram exactly as written. Before, it either broke delivery or was rendered as markup.ask_questionis unchanged: Telegram returns the parsed (unescaped) text, which still containsHuman input needed for <short id>..... The escaped payload can now be longer than 4096 bytes, which Telegram accepts because it counts characters after parsing entities.🤖 Generated with Claude Code