Closes #16700: Audit usage of mark_safe() for consistent escaping

This commit is contained in:
Jeremy Stretch 2024-06-24 11:34:46 -04:00
parent 8b62e40874
commit f4ac23d868
8 changed files with 16 additions and 13 deletions

View File

@ -1,6 +1,7 @@
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
import django_tables2 as tables import django_tables2 as tables
from django_tables2.utils import Accessor from django_tables2.utils import Accessor
from django.utils.html import escape
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
from dcim.models import Cable from dcim.models import Cable
@ -35,7 +36,7 @@ class CableTerminationsColumn(tables.Column):
def render(self, value): def render(self, value):
links = [ links = [
f'<a href="{term.get_absolute_url()}">{term}</a>' for term in self._get_terminations(value) f'<a href="{term.get_absolute_url()}">{escape(term)}</a>' for term in self._get_terminations(value)
] ]
return mark_safe('<br />'.join(links) or '&mdash;') return mark_safe('<br />'.join(links) or '&mdash;')

View File

@ -3410,8 +3410,9 @@ class VirtualChassisAddMemberView(ObjectPermissionRequiredMixin, GetReturnURLMix
if membership_form.is_valid(): if membership_form.is_valid():
membership_form.save() membership_form.save()
msg = f'Added member <a href="{device.get_absolute_url()}">{escape(device)}</a>' messages.success(request, mark_safe(
messages.success(request, mark_safe(msg)) f'Added member <a href="{device.get_absolute_url()}">{escape(device)}</a>'
))
if '_addanother' in request.POST: if '_addanother' in request.POST:
return redirect(request.get_full_path()) return redirect(request.get_full_path())

View File

@ -10,6 +10,7 @@ from django.contrib.postgres.fields import ArrayField
from django.core.validators import RegexValidator, ValidationError from django.core.validators import RegexValidator, ValidationError
from django.db import models from django.db import models
from django.urls import reverse from django.urls import reverse
from django.utils.html import escape
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
@ -520,7 +521,7 @@ class CustomField(CloningMixin, ExportTemplatesMixin, ChangeLoggedModel):
RegexValidator( RegexValidator(
regex=self.validation_regex, regex=self.validation_regex,
message=mark_safe(_("Values must match this regex: <code>{regex}</code>").format( message=mark_safe(_("Values must match this regex: <code>{regex}</code>").format(
regex=self.validation_regex regex=escape(self.validation_regex)
)) ))
) )
] ]

View File

@ -1,4 +1,5 @@
from django import template from django import template
from django.utils.html import escape
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
from core.models import ObjectType from core.models import ObjectType
@ -59,8 +60,7 @@ def custom_links(context, obj):
# Add non-grouped links # Add non-grouped links
else: else:
try: try:
rendered = cl.render(link_context) if rendered := cl.render(link_context):
if rendered:
template_code += LINK_BUTTON.format( template_code += LINK_BUTTON.format(
rendered['link'], rendered['link_target'], cl.button_class, rendered['text'] rendered['link'], rendered['link_target'], cl.button_class, rendered['text']
) )
@ -75,8 +75,7 @@ def custom_links(context, obj):
for cl in links: for cl in links:
try: try:
rendered = cl.render(link_context) if rendered := cl.render(link_context):
if rendered:
links_rendered.append( links_rendered.append(
GROUP_LINK.format(rendered['link'], rendered['link_target'], rendered['text']) GROUP_LINK.format(rendered['link'], rendered['link_target'], rendered['text'])
) )
@ -88,7 +87,7 @@ def custom_links(context, obj):
if links_rendered: if links_rendered:
template_code += GROUP_BUTTON.format( template_code += GROUP_BUTTON.format(
links[0].button_class, group, ''.join(links_rendered) links[0].button_class, escape(group), ''.join(links_rendered)
) )
return mark_safe(template_code) return mark_safe(template_code)

View File

@ -433,7 +433,7 @@ class LinkedCountColumn(tables.Column):
f'{k}={getattr(record, v) or settings.FILTERS_NULL_CHOICE_VALUE}' f'{k}={getattr(record, v) or settings.FILTERS_NULL_CHOICE_VALUE}'
for k, v in self.url_params.items() for k, v in self.url_params.items()
]) ])
return mark_safe(f'<a href="{url}">{value}</a>') return mark_safe(f'<a href="{url}">{escape(value)}</a>')
return value return value
def value(self, value): def value(self, value):

View File

@ -39,7 +39,7 @@ def handle_protectederror(obj_list, request, e):
if hasattr(dependent, 'get_absolute_url'): if hasattr(dependent, 'get_absolute_url'):
dependent_objects.append(f'<a href="{dependent.get_absolute_url()}">{escape(dependent)}</a>') dependent_objects.append(f'<a href="{dependent.get_absolute_url()}">{escape(dependent)}</a>')
else: else:
dependent_objects.append(str(dependent)) dependent_objects.append(escape(str(dependent)))
err_message += ', '.join(dependent_objects) err_message += ', '.join(dependent_objects)
messages.error(request, mark_safe(err_message)) messages.error(request, mark_safe(err_message))

View File

@ -58,7 +58,7 @@ def linkify(instance, attr=None):
url = instance.get_absolute_url() url = instance.get_absolute_url()
return mark_safe(f'<a href="{url}">{escape(text)}</a>') return mark_safe(f'<a href="{url}">{escape(text)}</a>')
except (AttributeError, TypeError): except (AttributeError, TypeError):
return text return escape(text)
@register.filter() @register.filter()

View File

@ -1,4 +1,5 @@
from django import template from django import template
from django.utils.html import escape
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
register = template.Library() register = template.Library()
@ -15,6 +16,6 @@ def nested_tree(obj):
nodes = obj.get_ancestors(include_self=True) nodes = obj.get_ancestors(include_self=True)
return mark_safe( return mark_safe(
' / '.join( ' / '.join(
f'<a href="{node.get_absolute_url()}">{node}</a>' for node in nodes f'<a href="{node.get_absolute_url()}">{escape(node)}</a>' for node in nodes
) )
) )