From c2ec0ee12be8b5bf55d048bf06ba18f9ba075997 Mon Sep 17 00:00:00 2001 From: tonghuaroot Date: Thu, 4 Jun 2026 11:56:32 +0800 Subject: [PATCH] Escape user-controlled element/collection names in CollectionElementDeleted log rendering LogEntryExtraFormatter::getInternalFormat() escapes user-controlled strings with htmlspecialchars() in every branch except the CollectionElementDeleted one, which interpolates getOldName() and getCollectionName() into the returned HTML unescaped. That string is rendered as raw HTML by LogEntryExtraColumn in the activity-log and element-history DataTables, so a name set on a deleted sub-element (parameter/attachment/lot/orderdetail) by a low-privileged editor is parsed as live markup in a log viewer's browser (stored XSS / HTML injection). Wrap both values in htmlspecialchars(), matching the sibling branches (e.g. ElementDeletedLogEntry at the old_name line). --- src/Services/LogSystem/LogEntryExtraFormatter.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Services/LogSystem/LogEntryExtraFormatter.php b/src/Services/LogSystem/LogEntryExtraFormatter.php index ae2a5eba..13394d98 100644 --- a/src/Services/LogSystem/LogEntryExtraFormatter.php +++ b/src/Services/LogSystem/LogEntryExtraFormatter.php @@ -169,8 +169,8 @@ class LogEntryExtraFormatter $array['log.collection_deleted.deleted'] = sprintf( '%s: %s (%s)', $this->elementTypeNameGenerator->getLocalizedTypeLabel($context->getDeletedElementClass()), - $context->getOldName() ?? (string) $context->getDeletedElementID(), - $context->getCollectionName() + htmlspecialchars($context->getOldName() ?? (string) $context->getDeletedElementID()), + htmlspecialchars($context->getCollectionName()) ); } @@ -218,4 +218,4 @@ class LogEntryExtraFormatter return implode(', ', $output); } -} +} \ No newline at end of file