CVE-2022-23656 (JavaScript, published 2022-03-02T21:15Z)
Description: value: Zulip is an open source team chat app. The `main` development branch of Zulip Server from June 2021 and later is vulnerable to a cross-site scripting vulnerability on the recent topics page. An attacker could maliciously craft a full name for their account and send messages to a topic with several participants; a victim who then opens an overflow tooltip including this full name on the recent topics page could trigger execution of JavaScript code controlled by the attacker. Users running a Zulip server from the main branch should upgrade from main (2022-03-01 or later) again to deploy this fix.
Severity: LOW (CVSS v3 base score: 5.4)
Weakness: CWE-79 \u2014 Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
Repository: https://github.com/zulip/zulip
Files changed:
static/js/popover_menus.js
static/js/recent_topics_ui.js
static/js/rendered_markdown.js
static/js/timerender.ts
static/js/tippyjs.js
static/js/ui_init.js
static/templates/compose.hbs
static/templates/compose_control_buttons.hbs
static/templates/recent_topic_row.hbs
static/templates/right_sidebar.hbs
Commit message: CVE-2022-23656: Fix cross-site scripting vulnerability in tooltips.

An attacker could maliciously craft a full name for their account and
send messages to a topic with several participants; a victim who then
opens an overflow tooltip including this full name on the recent
topics page could trigger execution of JavaScript code controlled by
the attacker.

Signed-off-by: Anders Kaseorg <anders@zulip.com>


Vulnerable code:
    allowHTML: true,
    const other_sender_names = displayed_other_names.join("<br/>");
        other_sender_names,
            $(this).attr("data-tippy-content", rendered_time.tooltip_content);
    tooltip_content: string;
    const tooltip_html_content = render_markdown_time_tooltip({tz_offset_str});
        tooltip_content: tooltip_html_content,
    // enable it by passing data-tippy-allowHtml="true"
        allowHTML: true,
            scroll_to_bottom_key: common.has_mac_keyboard()
        <div id="scroll-to-bottom-button-clickable-area"  data-tippy-content="{{t 'Scroll to bottom' }}  <span class='hotkey-hint'>({{scroll_to_bottom_key}})</span>" data-tippy-allowHtml="true">
    <a role="button" class="compose_control_button fa fa-clock-o time_pick" aria-label="{{t 'Add global time' }}" tabindex=0 data-tippy-content="{{t 'Add global time<br />Everyone sees global times in their own time zone.' }}" data-tippy-maxWidth="none" data-tippy-allowHtml="true"></a>
            <li class="recent_topics_participant_item tippy-zulip-tooltip" data-tippy-content="{{other_sender_names}}" data-tippy-allowHtml="true">
                <i class="fa fa-keyboard-o fa-2x tippy-zulip-tooltip" id="keyboard-icon" data-tippy-allowHtml="true" data-tippy-content="{{t 'Keyboard shortcuts' }} <span class='hotkey-hint'>(?)</span>"></i>

Fixed code:
        allowHTML: true,
        allowHTML: true,
        allowHTML: true,
        allowHTML: true,
import _ from "lodash";
    const other_sender_names_html = displayed_other_names
        .map((name) => _.escape(name))
        .join("<br />");
        other_sender_names_html,
            $(this)
                .attr("data-tippy-content", rendered_time.tooltip_content_html)
                .attr("data-tippy-allowHTML", "true");
    tooltip_content_html: string;
    const tooltip_content_html = render_markdown_time_tooltip({tz_offset_str});
        tooltip_content_html: tooltip_content_html,
    // enable it by passing data-tippy-allowHTML="true"
            scroll_to_bottom_key_html: common.has_mac_keyboard()
        <div id="scroll-to-bottom-button-clickable-area"  data-tippy-content="{{t 'Scroll to bottom' }}  &lt;span class='hotkey-hint'&gt;({{scroll_to_bottom_key_html}})&lt;/span&gt;" data-tippy-allowHTML="true">
    <a role="button" class="compose_control_button fa fa-clock-o time_pick" aria-label="{{t 'Add global time' }}" tabindex=0 data-tippy-content="{{t 'Add global time<br />Everyone sees global times in their own time zone.' }}" data-tippy-allowHTML="true" data-tippy-maxWidth="none"></a>
            <li class="recent_topics_participant_item tippy-zulip-tooltip" data-tippy-content="{{other_sender_names_html}}" data-tippy-allowHTML="true">
                <i class="fa fa-keyboard-o fa-2x tippy-zulip-tooltip" id="keyboard-icon" data-tippy-allowHTML="true" data-tippy-content="{{t 'Keyboard shortcuts' }} &lt;span class='hotkey-hint'&gt;(?)&lt;/span&gt;"></i>