From b1a8a9a4487c1629e850ef665a8f175d852a959a Mon Sep 17 00:00:00 2001 From: Seth Michael Larson Date: Tue, 28 Jul 2026 15:38:19 -0500 Subject: [PATCH] Allow Django to escape blog excerpt text in template --- apps/blogs/templates/blogs/index.html | 2 +- apps/blogs/tests/test_views.py | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/apps/blogs/templates/blogs/index.html b/apps/blogs/templates/blogs/index.html index 1ebffa862..7c91f8838 100644 --- a/apps/blogs/templates/blogs/index.html +++ b/apps/blogs/templates/blogs/index.html @@ -14,7 +14,7 @@

Welcome to the Python Inside

{{ latest_entry.title }}

-

{{ latest_entry.excerpt|striptags|truncatewords:50|safe }} +

{{ latest_entry.excerpt|striptags|truncatewords:50 }} Read more

{% endblock header_content %} diff --git a/apps/blogs/tests/test_views.py b/apps/blogs/tests/test_views.py index 887763d50..e4f8949f7 100644 --- a/apps/blogs/tests/test_views.py +++ b/apps/blogs/tests/test_views.py @@ -1,6 +1,7 @@ from django.core.management import call_command from django.test import TestCase from django.urls import reverse +from django.utils import timezone from apps.blogs.models import BlogEntry, Feed from apps.blogs.tests.utils import get_test_rss_path @@ -23,3 +24,17 @@ def test_blog_home(self): latest = BlogEntry.objects.latest() self.assertEqual(resp.context["latest_entry"], latest) + + def test_blog_home_escapes_excerpt(self): + """Excerpt from feed content must be auto-escaped, not marked safe.""" + feed = Feed.objects.create(name="test", website_url="http://example.org", feed_url="http://example.org/feed") + BlogEntry.objects.create( + title="Safe Post", + summary="

<img src=x onerror=alert(1)

", + pub_date=timezone.now(), + url="http://example.org/post", + feed=feed, + ) + resp = self.client.get(reverse("blog")) + self.assertNotContains(resp, "