Skip to content

Navigation Menu

Sign in
Appearance settings
Sign up
Appearance settings

[Notifier] Fix escaping of MarkdownV2 markup in TelegramTransport - #65644

#65644
Merged
nicolas-grekas merged 1 commit into
symfony:6.4symfony/symfony:6.4from
nicolas-grekas:telegram-markdownv2-escaping-64nicolas-grekas/symfony:telegram-markdownv2-escaping-64Copy head branch name to clipboard
Aug 25, 2026
Merged

[Notifier] Fix escaping of MarkdownV2 markup in TelegramTransport#65644
nicolas-grekas merged 1 commit into
symfony:6.4symfony/symfony:6.4from
nicolas-grekas:telegram-markdownv2-escaping-64nicolas-grekas/symfony:telegram-markdownv2-escaping-64Copy head branch name to clipboard

Conversation

@nicolas-grekas

Copy link
Copy Markdown
Member
Q A
Branch? 6.4
Bug fix? yes
New feature? no
Deprecations? no
Issues Fix #65626
License MIT

When the parse mode is not set or is MarkdownV2, TelegramTransport escapes reserved characters in the message text before sending it. The list of characters it escapes was adjusted by hand three times (#41600, #42721, #58636) and still contains three markup markers of MarkdownV2: ~ (strikethrough), | (||spoiler||) and > (block quotation). These formats cannot be used at all. Text that is already escaped by hand is escaped a second time (1\.2 becomes 1\\.2), which Telegram rejects.

This PR replaces the character list with the rule that Telegram's own parser applies: a reserved character is escaped when Telegram would reject it, and the markup is left alone.

  • Paired markers are never escaped: *bold*, _italic_, __underline__, `code`, ~strikethrough~, ||spoiler||, [link](url). The first five were already left alone since [Notifier] Improve Telegrams markdown escaping #58636; ~ and || now follow the same rule.
  • > is left alone at the start of a line, where it starts a block quotation, including the **> form of expandable quotations. It is escaped anywhere else.
  • ! is left alone in front of [, where it starts a custom emoji or a date-time entity. It is escaped anywhere else.
  • A character that is already escaped is kept as it is, so a message written as valid MarkdownV2 is sent unchanged.
  • ., #, +, -, =, {, } and a single | are escaped as before.

It also fixes the character class of the old pattern: +-= was read as a range from + to =, so digits, ,, /, :, ; and < were escaped too. Telegram accepts a backslash in front of any of them, so nothing was visible in the chat, but every digit counted twice towards the 4096-character limit.

Behavior change for plain-text senders: a message with an unescaped ~ or ||, or a line starting with >, is now sent as markup, the same way * and _ are since #58636. Plain text is sent as before when these characters are escaped in the message, or with the HTML parse mode.

Checks run:

  • ./phpunit src/Symfony/Component/Notifier/Bridge/Telegram on 6.4: OK, 70 tests, 161 assertions, 1 skipped (pre-existing).
  • Before the fix, the new case table fails on its first case and the existing escaping test fails on \~; both pass after it.
  • php-cs-fixer fix --dry-run on the touched files: clean.

Not covered: no call to the real Telegram API was made. The rules follow the MarkdownV2 section of the Bot API documentation.

Replaces #65643.

@nicolas-grekas nicolas-grekas added this to the 6.4 milestone Aug 25, 2026
@nicolas-grekas
nicolas-grekas merged commit 9814363 into symfony:6.4 Aug 25, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

Morty Proxy This is a proxified and sanitized view of the page, visit original site.