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).
This commit is contained in:
tonghuaroot 2026-06-04 11:56:32 +08:00 committed by Jan Böhmer
parent 6ae4381551
commit c2ec0ee12b

View file

@ -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);
}
}
}