Issue #16934: Escape config-revision banner values by default

Previous commit accidentally contained only docs work.

- Default to HTML-escaping banner values before displaying them
- Also default to escaping banner values in config form previews
- Escape names of dependent objects displayed when deleting parents
This commit is contained in:
Jeff Gehlbach 2024-07-19 10:28:03 -04:00
parent 7ab0345450
commit c85625b3d3
6 changed files with 30 additions and 6 deletions

View File

@ -4,6 +4,7 @@ import json
from django import forms
from django.conf import settings
from django.forms.fields import JSONField as _JSONField
from django.utils.html import escape
from django.utils.translation import gettext_lazy as _
from core.forms.mixins import SyncedDataMixin
@ -213,7 +214,10 @@ class ConfigRevisionForm(forms.ModelForm, metaclass=ConfigFormMetaclass):
help_text = self.fields[param.name].help_text
if help_text:
help_text += '<br />' # Line break
help_text += _('Current value: <strong>{value}</strong>').format(value=value or '&mdash;')
if param.name.startswith('BANNER_') and settings.ESCAPE_BANNERS:
help_text += _('Current value: <strong>{value}</strong>').format(value=escape(value) or '&mdash;')
else:
help_text += _('Current value: <strong>{value}</strong>').format(value=value or '&mdash;')
if value == param.default:
help_text += _(' (default)')
self.fields[param.name].help_text = help_text

View File

@ -131,6 +131,9 @@ EMAIL = {
'FROM_EMAIL': '',
}
# Setting this to False will allow banners to be rendered without HTML escaping for safety
ESCAPE_BANNERS = True
# Exempt certain models from the enforcement of view permissions. Models listed here will be viewable by all users and
# by anonymous users. List models in the form `<app>.<model>`. Add '*' to this list to exempt all models.
EXEMPT_VIEW_PERMISSIONS = [

View File

@ -92,6 +92,7 @@ DEVELOPER = getattr(configuration, 'DEVELOPER', False)
DJANGO_ADMIN_ENABLED = getattr(configuration, 'DJANGO_ADMIN_ENABLED', False)
DOCS_ROOT = getattr(configuration, 'DOCS_ROOT', os.path.join(os.path.dirname(BASE_DIR), 'docs'))
EMAIL = getattr(configuration, 'EMAIL', {})
ESCAPE_BANNERS = getattr(configuration, 'ESCAPE_BANNERS', True)
EVENTS_PIPELINE = getattr(configuration, 'EVENTS_PIPELINE', (
'extras.events.process_event_queue',
))

View File

@ -83,7 +83,11 @@ Blocks:
{# Top banner #}
{% if config.BANNER_TOP %}
{% include 'inc/banner.html' with content=config.BANNER_TOP %}
{% if not settings.ESCAPE_BANNERS %}
{% include 'inc/banner.html' with content=config.BANNER_TOP %}
{% else %}
{% include 'inc/banner.html' with content=config.BANNER_TOP|escape %}
{% endif %}
{% endif %}
{# /Top banner #}
@ -93,7 +97,11 @@ Blocks:
{% endif %}
{% if config.MAINTENANCE_MODE and config.BANNER_MAINTENANCE %}
{% include 'inc/alerts/warning.html' with title="Maintenance Mode" message=config.BANNER_MAINTENANCE|safe %}
{% if not settings.ESCAPE_BANNERS %}
{% include 'inc/alerts/warning.html' with title="Maintenance Mode" message=config.BANNER_MAINTENANCE|safe %}
{% else %}
{% include 'inc/alerts/warning.html' with title="Maintenance Mode" message=config.BANNER_MAINTENANCE|escape %}
{% endif %}
{% endif %}
{# /Alerts #}
@ -116,7 +124,11 @@ Blocks:
{# Bottom banner #}
{% if config.BANNER_BOTTOM %}
{% include 'inc/banner.html' with content=config.BANNER_BOTTOM %}
{% if not settings.ESCAPE_BANNERS %}
{% include 'inc/banner.html' with content=config.BANNER_BOTTOM %}
{% else %}
{% include 'inc/banner.html' with content=config.BANNER_BOTTOM|escape %}
{% endif %}
{% endif %}
{# /Bottom banner #}

View File

@ -17,7 +17,11 @@
{# Login banner #}
{% if config.BANNER_LOGIN %}
<div class="mb-5 text-center">
{{ config.BANNER_LOGIN|safe }}
{% if not settings.ESCAPE_BANNERS %}
{{ config.BANNER_LOGIN|safe }}
{% else %}
{{ config.BANNER_LOGIN|escape }}
{% endif %}
</div>
{% endif %}

View File

@ -29,7 +29,7 @@ def handle_protectederror(obj_list, request, e):
# Formulate the error message
err_message = _("Unable to delete <strong>{objects}</strong>. {count} dependent objects were found: ").format(
objects=', '.join(str(obj) for obj in obj_list),
objects=', '.join(escape(str(obj)) for obj in obj_list),
count=len(protected_objects) if len(protected_objects) <= 50 else _('More than 50')
)