VYPR
Moderate severityNVD Advisory· Published Dec 23, 2022· Updated Apr 9, 2025

Failure to Sanitize Special Elements into a Different Plane (Special Element Injection) in ikus060/rdiffweb

CVE-2022-4721

Description

Failure to Sanitize Special Elements into a Different Plane (Special Element Injection) in GitHub repository ikus060/rdiffweb prior to 2.5.5.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

CVE-2022-4721 is a special element injection vulnerability in rdiffweb before 2.5.5 that allows injection of hyperlinks in notification emails, enabling phishing attacks.

Vulnerability

Description

CVE-2022-4721 is a special element injection (improper neutralization of special elements) vulnerability present in rdiffweb versions prior to 2.5.5. The issue resides in the generation of email notification templates, where the application automatically converts certain text patterns into hyperlinks without proper sanitization. An attacker can inject specially crafted text that, when included in an email sent to users, is rendered as a clickable link pointing to an attacker-controlled destination [1][2].

Exploitation

To exploit this vulnerability, an attacker must control data that subsequently appears in an email notification. For example, if the attacker can create a repository with a malicious name or modify their profile information, that data may be inserted into email body templates. The attack does not require direct user interaction beyond the victim receiving the notification; the malicious hyperlink is automatically generated when the email is viewed in an HTML-capable client [2][3].

Impact

Successful exploitation allows an attacker to conduct phishing attacks by tricking users into clicking on injected links within official rdiffweb notification emails. This could lead to credential theft, malware delivery, or further compromise of the user's account or system. The impact is particularly severe because the email appears to come from the trusted rdiffweb instance [3][4].

Mitigation

The vulnerability was fixed in rdiffweb version 2.5.5. The commit disables the automatic hyperlink conversion in email templates, ensuring that user-controlled content is displayed as plain text rather than being transformed into active links. Users are strongly advised to update to version 2.5.5 or later to eliminate this injection vector [2][4].

AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
rdiffwebPyPI
< 2.5.52.5.5

Affected products

2
  • ghsa-coords
    Range: < 2.5.5
  • ikus060/ikus060/rdiffwebv5
    Range: unspecified

Patches

1
6afaae56a295

Disable automatic hyperlink in email template

https://github.com/ikus060/rdiffwebPatrik DufresneDec 21, 2022via ghsa
9 files changed · +45 28
  • rdiffweb/core/notification.py+2 2 modified
    @@ -73,7 +73,7 @@ def access_token_added(self, userobj, name):
     
             # Send a mail notification
             body = self.app.templates.compile_template(
    -            "access_token_added.html", **{"header_name": self.app.cfg.header_name, 'user': userobj, 'name': name}
    +            "email_access_token_added.html", **{"header_name": self.app.cfg.header_name, 'user': userobj, 'name': name}
             )
             self.bus.publish('queue_mail', to=userobj.email, subject=_("A new access token has been created"), message=body)
     
    @@ -118,7 +118,7 @@ def user_password_changed(self, userobj):
     
             # If the email attributes was changed, send a mail notification.
             body = self.app.templates.compile_template(
    -            "password_changed.html", **{"header_name": self.app.cfg.header_name, 'user': userobj}
    +            "email_password_changed.html", **{"header_name": self.app.cfg.header_name, 'user': userobj}
             )
             self.bus.publish('queue_mail', to=userobj.email, subject=_("Password changed"), message=body)
     
    
  • rdiffweb/core/tests/test_notification.py+5 5 modified
    @@ -64,7 +64,7 @@ def test_notification_job(self):
             self.listener.queue_email.assert_called_once_with(
                 to='test@test.com',
                 subject='Notification',
    -            message="<html>\n  <head></head>\n  <body>\n    Hey admin,\n    <p>\n      You are receiving this email to notify you about your backups. The\n      following repositories are inactive for some time. We invite you to have a look\n      at your last backup schedule.\n    </p>\n    <ul>\n      <li>testcases</li>\n    </ul>\n    <p>\n      If you don't want to be notify about this. You need to review your\n      user preferences.\n    </p>\n  </body>\n</html>",
    +            message="<html>\n  <head></head>\n  <body>\n    <p>\n      <a>Hey admin,</a>\n    </p>\n    <p>\n      You are receiving this email to notify you about your backups. The\n      following repositories are inactive for some time. We invite you to have a look\n      at your last backup schedule.\n    </p>\n    <ul>\n      \n        <li>\n          <a>testcases</a>\n        </li>\n      \n    </ul>\n    <p>If you don't want to be notify about this. You need to review your user preferences.</p>\n  </body>\n</html>",
             )
     
         def test_notification_job_undefined_last_backup_date(self):
    @@ -85,7 +85,7 @@ def test_notification_job_undefined_last_backup_date(self):
             self.listener.queue_email.assert_called_once_with(
                 to='test@test.com',
                 subject='Notification',
    -            message="<html>\n  <head></head>\n  <body>\n    Hey admin,\n    <p>\n      You are receiving this email to notify you about your backups. The\n      following repositories are inactive for some time. We invite you to have a look\n      at your last backup schedule.\n    </p>\n    <ul>\n      <li>broker-repo</li>\n    </ul>\n    <p>\n      If you don't want to be notify about this. You need to review your\n      user preferences.\n    </p>\n  </body>\n</html>",
    +            message="<html>\n  <head></head>\n  <body>\n    <p>\n      <a>Hey admin,</a>\n    </p>\n    <p>\n      You are receiving this email to notify you about your backups. The\n      following repositories are inactive for some time. We invite you to have a look\n      at your last backup schedule.\n    </p>\n    <ul>\n      \n        <li>\n          <a>broker-repo</a>\n        </li>\n      \n    </ul>\n    <p>If you don't want to be notify about this. You need to review your user preferences.</p>\n  </body>\n</html>",
             )
     
         def test_notification_job_without_notification(self):
    @@ -135,7 +135,7 @@ def test_email_changed(self):
             self.listener.queue_email.assert_called_once_with(
                 to='original_email@test.com',
                 subject='Email address changed',
    -            message='<html>\n  <head></head>\n  <body>\n    Hey admin,\n    <p>You recently changed the email address associated with your Rdiffweb account.</p>\n    <p>\n      If you did not make this change and believe your account has been compromised, please contact your administrator.\n    </p>\n  </body>\n</html>',
    +            message='<html>\n  <head></head>\n  <body>\n    <p>\n      <a>Hey admin,</a>\n    </p>\n    <p>\n      <a>You recently changed the email address associated with your Rdiffweb account.</a>\n    </p>\n    <p>\n      If you did not make this change and believe your account has been compromised, please contact your administrator.\n    </p>\n  </body>\n</html>',
             )
     
         def test_email_updated_with_same_value(self):
    @@ -167,7 +167,7 @@ def test_password_change_notification(self):
             self.listener.queue_email.assert_called_once_with(
                 to='password_change@test.com',
                 subject='Password changed',
    -            message='<html>\n  <head></head>\n  <body>\n    Hey admin,\n    <p>You recently changed the password associated with your Rdiffweb account.</p>\n    <p>\n      If you did not make this change and believe your account has been compromised, please contact your administrator.\n    </p>\n  </body>\n</html>',
    +            message='<html>\n  <head></head>\n  <body>\n    <p>\n      <a>Hey admin,</a>\n    </p>\n    <p>You recently changed the password associated with your Rdiffweb account.</p>\n    <p>\n      If you did not make this change and believe your account has been compromised, please contact your administrator.\n    </p>\n  </body>\n</html>',
             )
     
         def test_password_change_with_same_value(self):
    @@ -186,5 +186,5 @@ def test_password_change_with_same_value(self):
             self.listener.queue_email.assert_called_once_with(
                 to='password_change@test.com',
                 subject='Password changed',
    -            message='<html>\n  <head></head>\n  <body>\n    Hey admin,\n    <p>You recently changed the password associated with your Rdiffweb account.</p>\n    <p>\n      If you did not make this change and believe your account has been compromised, please contact your administrator.\n    </p>\n  </body>\n</html>',
    +            message='<html>\n  <head></head>\n  <body>\n    <p>\n      <a>Hey admin,</a>\n    </p>\n    <p>You recently changed the password associated with your Rdiffweb account.</p>\n    <p>\n      If you did not make this change and believe your account has been compromised, please contact your administrator.\n    </p>\n  </body>\n</html>',
             )
    
  • rdiffweb/templates/access_token_added.html+0 10 removed
    @@ -1,10 +0,0 @@
    -<html>
    -  <head></head>
    -  <body>
    -    {% trans username=user.username %}Hey {{ username }},{% endtrans %}
    -    <p>{% trans %}A new access token, named "{{ name }}", has been created.{% endtrans %}</p>
    -    <p>
    -      {% trans %}If you did not make this change and believe your account has been compromised, please contact your administrator.{% endtrans %}
    -    </p>
    -  </body>
    -</html>
    
  • rdiffweb/templates/email_access_token_added.html+14 0 added
    @@ -0,0 +1,14 @@
    +<html>
    +  <head></head>
    +  <body>
    +    <p>
    +      <a>{% trans username=(user.fullname or user.username) %}Hey {{ username }},{% endtrans %}</a>
    +    </p>
    +    <p>
    +      <a>{% trans %}A new access token, named "{{ name }}", has been created.{% endtrans %}</a>
    +    </p>
    +    <p>
    +      {% trans %}If you did not make this change and believe your account has been compromised, please contact your administrator.{% endtrans %}
    +    </p>
    +  </body>
    +</html>
    
  • rdiffweb/templates/email_changed.html+6 2 modified
    @@ -1,8 +1,12 @@
     <html>
       <head></head>
       <body>
    -    {% trans username=(user.fullname or user.username) %}Hey {{ username }},{% endtrans %}
    -    <p>{% trans %}You recently changed the email address associated with your {{ header_name }} account.{% endtrans %}</p>
    +    <p>
    +      <a>{% trans username=(user.fullname or user.username) %}Hey {{ username }},{% endtrans %}</a>
    +    </p>
    +    <p>
    +      <a>{% trans %}You recently changed the email address associated with your {{ header_name }} account.{% endtrans %}</a>
    +    </p>
         <p>
           {% trans %}If you did not make this change and believe your account has been compromised, please contact your administrator.{% endtrans %}
         </p>
    
  • rdiffweb/templates/email_mfa.html+3 1 modified
    @@ -1,7 +1,9 @@
     <html>
       <head></head>
       <body>
    -    {% trans username=(user.fullname or user.username) %}Hey {{ username }},{% endtrans %}
    +    <p>
    +      <a>{% trans username=(user.fullname or user.username) %}Hey {{ username }},{% endtrans %}</a>
    +    </p>
         <p>
           {% if user.mfa %}
             {% trans %}Your {{ header_name }} Account is now protected with Two-Factor Authentication. When you sign in on a new or untrusted device, you'll need your second factor to verify your identity.{% endtrans %}
    
  • rdiffweb/templates/email_notification.html+9 6 modified
    @@ -1,18 +1,21 @@
     <html>
       <head></head>
       <body>
    -    {% trans username=(user.fullname or user.username) %}Hey {{ username }},{% endtrans %}
    +    <p>
    +      <a>{% trans username=(user.fullname or user.username) %}Hey {{ username }},{% endtrans %}</a>
    +    </p>
         <p>
           {% trans %}You are receiving this email to notify you about your backups. The
           following repositories are inactive for some time. We invite you to have a look
           at your last backup schedule.{% endtrans %}
         </p>
         <ul>
    -      {% for r in repos %}<li>{{ r.display_name }}</li>{% endfor %}
    +      {% for r in repos %}
    +        <li>
    +          <a>{{ r.display_name }}</a>
    +        </li>
    +      {% endfor %}
         </ul>
    -    <p>
    -      {% trans %}If you don't want to be notify about this. You need to review your
    -      user preferences.{% endtrans %}
    -    </p>
    +    <p>{% trans %}If you don't want to be notify about this. You need to review your user preferences.{% endtrans %}</p>
       </body>
     </html>
    
  • rdiffweb/templates/email_password_changed.html+3 1 renamed
    @@ -1,7 +1,9 @@
     <html>
       <head></head>
       <body>
    -    {% trans username=user.username %}Hey {{ username }},{% endtrans %}
    +    <p>
    +      <a>{% trans username=(user.fullname or user.username) %}Hey {{ username }},{% endtrans %}</a>
    +    </p>
         <p>{% trans %}You recently changed the password associated with your {{ header_name }} account.{% endtrans %}</p>
         <p>
           {% trans %}If you did not make this change and believe your account has been compromised, please contact your administrator.{% endtrans %}
    
  • rdiffweb/templates/email_verification_code.html+3 1 modified
    @@ -1,7 +1,9 @@
     <html>
       <head></head>
       <body>
    -    {% trans username=(user.fullname or user.username) %}Hey {{ username }},{% endtrans %}
    +    <p>
    +      <a>{% trans username=(user.fullname or user.username) %}Hey {{ username }},{% endtrans %}</a>
    +    </p>
         <p>
           {% trans %}To help us make sure it's really you, here's the verification code you'll need to log in:{% endtrans %}
         </p>
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.