CVE-2021-21333 (Python, published 2021-03-26T20:15Z)
Description: value: Synapse is a Matrix reference homeserver written in python (pypi package matrix-synapse). Matrix is an ecosystem for open federated Instant Messaging and VoIP. In Synapse before version 1.27.0, the notification emails sent for notifications for missed messages or for an expiring account are subject to HTML injection. In the case of the notification for missed messages, this could allow an attacker to insert forged content into the email. The account expiry feature is not enabled by default and the HTML injection is not controllable by an attacker. This is fixed in version 1.27.0.
Severity: LOW (CVSS v3 base score: 6.1)
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/matrix-org/synapse
Files changed:
UPGRADE.rst
changelog.d/9200.misc
synapse/config/_base.py
synapse/config/captcha.py
synapse/config/consent_config.py
synapse/config/registration.py
synapse/push/mailer.py
synapse/res/templates/sso_auth_bad_user.html
synapse/res/templates/sso_auth_confirm.html
synapse/res/templates/sso_error.html
synapse/res/templates/sso_login_idp_picker.html
synapse/res/templates/sso_redirect_confirm.html
Commit message: Clean-up the template loading code. (#9200)

* Enables autoescape by default for HTML files.
* Adds a new read_template method for reading a single template.
* Some logic clean-up.

Vulnerable code:
        self,
        filenames: List[str],
        custom_template_directory: Optional[str] = None,
        autoescape: bool = False,
        Files read are treated as Jinja templates. These templates are not rendered yet.
            autoescape: Whether to autoescape variables before inserting them into the
                template.

        templates = []
        env = jinja2.Environment(loader=loader, autoescape=autoescape)
        for filename in filenames:
            # Load the template
            template = env.get_template(filename)
            templates.append(template)

        return templates
        self.recaptcha_template = self.read_templates(
            ["recaptcha.html"], autoescape=True
        )[0]
        self.terms_template = self.read_templates(["terms.html"], autoescape=True)[0]
        self.fallback_success_template = self.read_templates(
            ["auth_success.html"], autoescape=True
        )[0]
    Process text: treat it as HTML but escape any tags (ie. just escape the
    HTML) then linkify it.
                We were unable to validate your <tt>{{server_name | e}}</tt> account via
                A client is trying to {{ description | e }}. To confirm this action,
                <a href="{{ redirect_url | e }}">re-authenticate with single sign-on</a>.
    <div id="errormsg" style="margin:20px 80px">{{ error_description | e }}</div>
        <title>{{server_name | e}} Login</title>
            <h1 id="title">{{server_name | e}} Login</h1>
                <input type="hidden" name="redirectUrl" value="{{redirect_url | e}}">
                        <input type="radio" name="idp" id="prov{{loop.index}}" value="{{p.idp_id}}">
                        <label for="prov{{loop.index}}">{{p.idp_name | e}}</label>
                        <img src="{{p.idp_icon | mxc_to_http(32, 32)}}"/>
        <p>The application at <span style="font-weight:bold">{{ display_url | e }}</span> is requesting full access to your <span style="font-weight:bold">{{ server_name }}</span> Matrix account.</p>
            <a href="{{ redirect_url | e }}">I trust this address</a>
</html>

Fixed code:
Upgrading to v1.27.0
====================

Changes to HTML templates
-------------------------

The HTML templates for SSO and email notifications now have `Jinja2's autoescape <https://jinja.palletsprojects.com/en/2.11.x/api/#autoescaping>`_
enabled for files ending in ``.html``, ``.htm``, and ``.xml``. If you hae customised
these templates and see issues when viewing them you might need to update them.
It is expected that most configurations will need no changes.

If you have customised the templates *names* for these templates it is recommended
to verify they end in ``.html`` to ensure autoescape is enabled.

The above applies to the following templates:

* ``add_threepid.html``
* ``add_threepid_failure.html``
* ``add_threepid_success.html``
* ``notice_expiry.html``
* ``notice_expiry.html``
* ``notif_mail.html`` (which, by default, includes ``room.html`` and ``notif.html``)
* ``password_reset.html``
* ``password_reset_confirmation.html``
* ``password_reset_failure.html``
* ``password_reset_success.html``
* ``registration.html``
* ``registration_failure.html``
* ``registration_success.html``
* ``sso_account_deactivated.html``
* ``sso_auth_bad_user.html``
* ``sso_auth_confirm.html``
* ``sso_auth_success.html``
* ``sso_error.html``
* ``sso_login_idp_picker.html``
* ``sso_redirect_confirm.html``

Clean-up template loading code.
    def read_template(self, filename: str) -> jinja2.Template:
        """Load a template file from disk.

        This function will attempt to load the given template from the default Synapse
        template directory.

        Files read are treated as Jinja templates. The templates is not rendered yet
        and has autoescape enabled.

        Args:
            filename: A template filename to read.

        Raises:
            ConfigError: if the file's path is incorrect or otherwise cannot be read.

        Returns:
            A jinja2 template.
        """
        return self.read_templates([filename])[0]

        self, filenames: List[str], custom_template_directory: Optional[str] = None,
        Files read are treated as Jinja templates. The templates are not rendered yet
        and have autoescape enabled.
        env = jinja2.Environment(loader=loader, autoescape=jinja2.select_autoescape(),)
        # Load the templates
        return [env.get_template(filename) for filename in filenames]
        self.recaptcha_template = self.read_template("recaptcha.html")
        self.terms_template = self.read_template("terms.html")
        self.fallback_success_template = self.read_template("auth_success.html")
    """
    Sanitise a raw HTML string to a set of allowed tags and attributes, and linkify any bare URLs.

    Args
        raw_html: Unsafe HTML.

    Returns:
        A Markup object ready to safely use in a Jinja template.
    """
    Sanitise text (escape any HTML tags), and then linkify any bare URLs.

    Args
        raw_text: Unsafe text which might include HTML markup.

    Returns:
        A Markup object ready to safely use in a Jinja template.
                We were unable to validate your <tt>{{ server_name }}</tt> account via
                A client is trying to {{ description }}. To confirm this action,
                <a href="{{ redirect_url }}">re-authenticate with single sign-on</a>.
    <div id="errormsg" style="margin:20px 80px">{{ error_description }}</div>
        <title>{{ server_name }} Login</title>
            <h1 id="title">{{ server_name }} Login</h1>
                <input type="hidden" name="redirectUrl" value="{{ redirect_url }}">
                        <input type="radio" name="idp" id="prov{{ loop.index }}" value="{{ p.idp_id }}">
                        <label for="prov{{ loop.index }}">{{ p.idp_name }}</label>
                        <img src="{{ p.idp_icon | mxc_to_http(32, 32) }}"/>
        <p>The application at <span style="font-weight:bold">{{ display_url }}</span> is requesting full access to your <span style="font-weight:bold">{{ server_name }}</span> Matrix account.</p>
            <a href="{{ redirect_url }}">I trust this address</a>
</html>