diff --git a/changedetectionio/tests/smtp/test_notification_smtp.py b/changedetectionio/tests/smtp/test_notification_smtp.py index ec646c8c..a163c6f6 100644 --- a/changedetectionio/tests/smtp/test_notification_smtp.py +++ b/changedetectionio/tests/smtp/test_notification_smtp.py @@ -108,7 +108,9 @@ def test_check_notification_email_formats_default_HTML(client, live_server, meas html_content = html_part.get_content() assert 'some text
' in html_content # We converted \n from the notification body assert 'fallback-body
' in html_content # kept the original
- assert '(added) So let\'s see what happens.
' in html_content # the html part + # GHSA-q8xq-qg4x-wphg: apostrophes in diff content are escaped (') for HTML notifications. + # Renders as ' in the recipient's email client; only the byte-source differs. + assert '(added) So let's see what happens.
' in html_content # the html part delete_all_watches(client) @@ -452,7 +454,8 @@ def test_check_notification_email_formats_default_Text_override_HTML(client, liv html_part = parts[1] assert html_part.get_content_type() == 'text/html' html_content = html_part.get_content() - assert '(removed) So let\'s see what happens.' in html_content # the html part + # GHSA-q8xq-qg4x-wphg: apostrophes in diff content are escaped (') for HTML notifications. + assert '(removed) So let's see what happens.' in html_content # the html part assert '<!DOCTYPE html' not in html_content assert '' in html_content # We converted \n from the notification body assert 'fallback-body
' in html_content # kept the original
- assert '(added) So let\'s see what happens.
' in html_content # the html part + # GHSA-q8xq-qg4x-wphg: apostrophes in diff content are escaped (') for HTML notifications. + assert '(added) So let's see what happens.
' in html_content # the html part delete_all_watches(client) \ No newline at end of file diff --git a/changedetectionio/tests/test_notification.py b/changedetectionio/tests/test_notification.py index 1d666793..04765165 100644 --- a/changedetectionio/tests/test_notification.py +++ b/changedetectionio/tests/test_notification.py @@ -790,3 +790,79 @@ def test_html_watch_diff_content_escaped_in_html_notification(client, live_serve f"Diff content from text/html page was NOT escaped — tracking pixel reached HTML notification: {body!r}" client.get(url_for("ui.form_delete", uuid="all"), follow_redirects=True) + + +def test_source_url_diff_content_escaped_in_html_notification(client, live_server, measure_memory_usage, datastore_path): + """ + GHSA-q8xq-qg4x-wphg — companion to the inscriptis test. `source:`-prefixed + URLs short-circuit the HTML→text step (processor.py:509-511) and store the + raw HTML body verbatim as the snapshot. That gives an attacker who controls + a watched page a *direct* injection path — no entity-encoding tricks needed, + any live `` / `` / `