Skip to content

fix: escape user input in notification content templates - #323

Merged
Gi-ron merged 1 commit into
ednx-release/teak.masterfrom
sgb/backport-notification-escape-teak
Jul 28, 2026
Merged

fix: escape user input in notification content templates#323
Gi-ron merged 1 commit into
ednx-release/teak.masterfrom
sgb/backport-notification-escape-teak

Conversation

@Gi-ron

@Gi-ron Gi-ron commented Jul 27, 2026

Copy link
Copy Markdown

Summary

  • Backport of openedx/openedx-platform@52f2b3b to our Teak release branch
  • HTML-escapes user-controlled context values in get_notification_content before str.format(**context), fixing stored CSS injection in digest and batched notification emails
  • Closes GHSA-rv5w-f4r5-h77g for our Teak-based deployments

Context

The official fix landed on Ulmo, Verawood and master on July 13, 2026 but did not include Teak. Since base_notification.py is unchanged in our Teak branch relative to upstream, this cherry-pick applies cleanly with no conflicts.

Discussion thread titles (and other user-controlled context fields — replier_name, author_name, username) were interpolated raw into notification.content via str.format(**context). That output is rendered with Django's |safe filter in digest_content.html, which is included by both the email_digest and batched_email body templates, so a <style> block in a thread title survived into recipient inboxes as executable CSS on email open — enabling open-tracking, content spoofing, and phishing.

This is the incomplete-patch companion of GHSA-4xv3-5j4x-q8g4 (CVE-2026-42857), which sanitized the post body via clean_thread_html_body() but did not cover the title path.

Discussion thread titles (and other user-controlled context fields —
replier_name, author_name, username) were interpolated raw into
notification.content via `str.format(**context)`. That output is
rendered with Django's `|safe` filter in digest_content.html, which
is included by both the email_digest and batched_email body
templates, so a `<style>` block in a thread title survived into
recipient inboxes as executable CSS on email open — enabling
open-tracking, content spoofing, and phishing.

Escape at the source: in `get_notification_content`, wrap every
context value with `django.utils.html.escape` before
`template.format(**context)`, exempting the two structural keys
(`p`, `strong`) that content_templates use as HTML tag names. This
defends every renderer of `notification.content` in one place.

This is the incomplete-patch companion of GHSA-4xv3-5j4x-q8g4
(CVE-2026-42857), which sanitized the post body via
`clean_thread_html_body()` but did not cover the title path.
Fixes GHSA-rv5w-f4r5-h77g.

(cherry picked from commit 08b719ce41bb369fa0cabbe8d0547124e64c8566)
(cherry picked from commit 52f2b3b)
@Gi-ron
Gi-ron merged commit 54108a3 into ednx-release/teak.master Jul 28, 2026
46 of 47 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants