Telegram Desktop's HTML chat export feature carried a stored cross-site scripting flaw that let a crafted message run script when an exported file was opened in a browser, according to a community write-up published on dev.to. The post attributes the discovery to security researchers Denis Rostilov and Aleksander Rostilov of ExPatch Vulnerability Research, with disclosure on September 12, 2026, after Telegram patched the issue in July. The account is a single community source, not an independent verification, and the author states the material comes from the ExPatch write-up and the project's public commit history rather than personal use of the feature.
The write-up says no CVE number was assigned and Telegram published no dedicated security advisory for the flaw. It also states the vulnerable line of code remained in stable releases for roughly two years and four months. Those specifics are the author's characterization of the disclosure record and should be read as attributed claims rather than confirmed by a second source in the supplied evidence.
What gets described is a narrow mechanism. Inside export_output_html.cpp, a function called SerializeString() handled three things: hex encoding of ASCII control characters, conversion of newlines into <br> tags, and escaping of five HTML-dangerous characters. During export, message text, sender names and other user-controlled fields all received that treatment. Per the write-up, inline keyboard button text did not — there the code appended the button text directly. Commit 8457d13a, authored by developer John Preston, is the described fix; it wraps that same value in SerializeString(). The post also says that commit addressed a second flaw in the same file: copy-button content was placed inside an onclick handler's JavaScript string, with backslashes and single quotes left unescaped.
Why the desktop app itself did not show the problem is central to the write-up's explanation. Telegram Desktop renders messages through its own UI framework rather than a browser engine, so a literal script tag in button text appeared as plain characters. The post says the researchers padded the payload with invisible Unicode characters so the button looked empty in the app they tested. The payload only became active when the export pipeline wrote the same string into an HTML file and a browser interpreted it as markup.
This is framed by the write-up as a split-brain trust problem: the same data is processed by two consumers whose rules differ, and the safe treatment for one is silently assumed to apply to the other. As a general illustration of the pattern — not a documented incident, the author's example only — it offers user input stored as JSON and then serialized into HTML emails, a webview, or a PDF generator that renders HTML, where the original interface escaped the value at render time but the new consumer did not.
The delivery chain described depends on three Telegram-specific mechanics. The write-up says bots can attach inline keyboards whose button text the bot fully controls, and the Bot API accepts arbitrary Unicode there, including HTML tags; URL-only inline keyboards survive forwarding; and the bot never needs to join the target group, because an attacker can send the crafted message to a collaborator or their own account and have someone forward it into the target group. The post states the payload then sits in that group's permanent history until someone runs an export.
Messages never reach the bot's script through the Bot API, according to the write-up; instead it reads them from the exported document in the victim's browser after the fact, which the author says bypasses Telegram's bot privacy model that normally hides ordinary group traffic from bots by default. CVSS 3.1 8.2 (High) with a scope-changed vector is the rating the post reports from the researchers, because the impact lands in a context the Bot API was not supposed to reach.
Per the write-up, when an export file was opened with JavaScript enabled, the injected script could reach: text, sender names and timestamps among all messages in the file, parsed from the DOM and sent to an attacker-controlled server; chat metadata such as the chat name, whether it is private or a group, and member count; and the local file path via location.href, which the author says leaks the operating system username and directory structure. The script also controls the DOM, it says, and the researchers' proof of concept swapped the entire export for a fake Telegram-branded verification form. Through that same control, rendered timestamps, sender names and message text could likewise be silently altered, according to the post.
The write-up states an explicit scope limitation: Telegram Desktop breaks long exports into separate files holding 1,000 messages apiece, so a single poisoned file exposes only its own portion of the conversation rather than the whole account. The author notes that limitation is real, while arguing that a thousand messages from a work group or legal discussion is often precisely the material someone cannot afford to have leaked or falsified.
Coverage underplays the history-tampering angle, the post argues, because records in disputes, investigations and compliance reviews are what chat exports are used as. A bug that lets an attacker rewrite what an export displays, without touching Telegram's servers, is described as a record-tampering vector at the presentation layer, with the victim seeing their own file in their own browser showing their own conversation.
Remediation is covered in the write-up: code was fixed by Telegram during early July 2026 — on July 3 the beta 6.9.4 arrived, followed on July 14 by stable 7.0.1. Export files already sitting on disk are not reached by patching the app, it stresses, so an executable payload may still be carried by a file that a vulnerable build produced. What the recommendations relay: Telegram Desktop should be updated to 7.0.1 or a newer release (or 6.9.4+ if on the beta channel); chats exported to HTML earlier should be re-exported and the old files deleted; any retained old export should be opened only with JavaScript disabled; and every pre-fix export from a large group should be treated as untrusted, since which message carries the payload cannot be eyeballed in any way.
No evidence of real-world exploitation had been reported by the researchers as of the September 12 disclosure, the write-up states. That is reassuring and mostly irrelevant to the engineering lesson, the author calls it, since the same pattern applies to the next export feature in whatever app ships it.
For freelancers, designers and developers, the practical takeaway is an audit of any feature that writes user-controlled data into HTML: report generators, invoice pipelines with an HTML intermediate step, test-result dashboards written to disk, and chat or data exports. What the write-up's checklist suggests: inventory every field that reaches the output — button labels, alt text, filenames, header attributes and anything embedded in inline event handlers, where JavaScript-string escaping is required in addition to HTML escaping; funnel every field through one escaping function; and search output-writing code for string concatenation that bypasses it. In Telegram's case, the author notes, a single search for append calls in the export file would have surfaced the miss.
The write-up also advises against treating the primary UI as proof of sanitization, since safe rendering in the app says nothing about a second consumer such as an exported file or a webview; assuming forwarding, copying and re-sharing; versioning output files so old exports outliving a security fix can be flagged; and preferring a templating engine with auto-escaping over manual string building, while auditing any deliberate bypass. These are the author's recommendations, not independently tested findings.
Several things remain unknown or unverified in the supplied evidence. There is no independent confirmation of the timeline, the commit, the CVSS score or the absence of a CVE beyond the community post's account. The write-up does not quantify how many users or exports were affected, does not describe any confirmed exploitation, and does not say whether Telegram issued user-facing guidance. The author's transparency note states they have not used the export feature themselves, which limits the account to a secondary description of the ExPatch research and public commit history.
The broader lesson the write-up draws is that escaping failures rarely stem from teams not knowing what escaping is; they happen when a template has many fields, most are escaped, and one is treated as just a label even though labels come from users. The author's closing argument is that the bug survived on the gap between fields developers remember are dangerous and fields filed under just text, and that the checklist is worth running against one's own exporters. That conclusion is editorial analysis from the source, not a measured result.