From 1af8e37e9bf2c1629866cd166d6f2cc80760226b Mon Sep 17 00:00:00 2001
From: "potsda.mn-Kollektiv"
Date: Thu, 7 Dec 2023 14:28:59 +0100
Subject: [PATCH] fix(front-end): add more security fixes for formatted lists
and notifier
- introduce html escape function
- escape message content in notifier plugin
- escape user name in ConversationListItem
- escape user name in the Event EditView contacts section
- display user summary as plain text in ActorCard
Signed-off-by: Thomas Citharel
---
src/components/Account/ActorCard.vue | 11 ++++++++++-
src/components/Conversations/ConversationListItem.vue | 3 ++-
src/plugins/notifier.ts | 3 ++-
src/utils/html.ts | 10 ++++++++++
src/views/Event/EditView.vue | 3 ++-
5 files changed, 26 insertions(+), 4 deletions(-)
diff --git a/src/components/Account/ActorCard.vue b/src/components/Account/ActorCard.vue
index 2124b746d..6856a2bd0 100644
--- a/src/components/Account/ActorCard.vue
+++ b/src/components/Account/ActorCard.vue
@@ -30,7 +30,7 @@
@{{ usernameWithDomain(actor) }}
+
{
const formattedListOfParticipants = computed(() => {
return formatList(
otherParticipants.value.map(
- (participant) => `${displayName(participant)}`
+ (participant) => `${escapeHtml(displayName(participant))}`
)
);
});
diff --git a/src/plugins/notifier.ts b/src/plugins/notifier.ts
index 0b5e9c3fe..23719b706 100644
--- a/src/plugins/notifier.ts
+++ b/src/plugins/notifier.ts
@@ -1,3 +1,4 @@
+import { escapeHtml } from "@/utils/html";
import { App } from "vue";
export class Notifier {
@@ -21,7 +22,7 @@ export class Notifier {
private notification(message: string, type: string) {
this.app.config.globalProperties.$oruga.notification.open({
- message,
+ message: escapeHtml(message),
duration: 5000,
position: "bottom-right",
type,
diff --git a/src/utils/html.ts b/src/utils/html.ts
index 02b8763b4..7f0ac34a9 100644
--- a/src/utils/html.ts
+++ b/src/utils/html.ts
@@ -5,3 +5,13 @@ export const getValueFromMeta = (name: string): string | null => {
}
return null;
};
+
+export function escapeHtml(html: string) {
+ const p = document.createElement("p");
+ p.appendChild(document.createTextNode(html.trim()));
+
+ const escapedContent = p.innerHTML;
+ p.remove();
+
+ return escapedContent;
+}
diff --git a/src/views/Event/EditView.vue b/src/views/Event/EditView.vue
index d833d8dea..3d9deba6c 100644
--- a/src/views/Event/EditView.vue
+++ b/src/views/Event/EditView.vue
@@ -180,7 +180,7 @@
{
contact: formatList(
event.contacts.map((contact) =>
- displayNameAndUsername(contact)
+ escapeHtml(displayNameAndUsername(contact))
)
),
},
@@ -628,6 +628,7 @@ import { useHead } from "@unhead/vue";
import { useProgrammatic } from "@oruga-ui/oruga-next";
import type { Locale } from "date-fns";
import sortBy from "lodash/sortBy";
+import { escapeHtml } from "@/utils/html";
const DEFAULT_LIMIT_NUMBER_OF_PLACES = 10;